rust/hg-core/src/repo.rs
branchstable
changeset 50658 1e2c6cda2309
parent 50252 a6b8b1ab9116
child 50660 bf16ef96defe
equal deleted inserted replaced
50657:e77ca247b85b 50658:1e2c6cda2309
   230         f: impl FnOnce() -> R,
   230         f: impl FnOnce() -> R,
   231     ) -> Result<R, LockError> {
   231     ) -> Result<R, LockError> {
   232         try_with_lock_no_wait(self.hg_vfs(), "wlock", f)
   232         try_with_lock_no_wait(self.hg_vfs(), "wlock", f)
   233     }
   233     }
   234 
   234 
   235     pub fn has_dirstate_v2(&self) -> bool {
   235     /// Whether this repo should use dirstate-v2.
       
   236     /// The presence of `dirstate-v2` in the requirements does not mean that
       
   237     /// the on-disk dirstate is necessarily in version 2. In most cases,
       
   238     /// a dirstate-v2 file will indeed be found, but in rare cases (like the
       
   239     /// upgrade mechanism being cut short), the on-disk version will be a
       
   240     /// v1 file.
       
   241     /// Semantically, having a requirement only means that a client should be
       
   242     /// able to understand the repo *if* it uses the requirement, but not that
       
   243     /// the requirement is actually used.
       
   244     pub fn use_dirstate_v2(&self) -> bool {
   236         self.requirements
   245         self.requirements
   237             .contains(requirements::DIRSTATE_V2_REQUIREMENT)
   246             .contains(requirements::DIRSTATE_V2_REQUIREMENT)
   238     }
   247     }
   239 
   248 
   240     pub fn has_sparse(&self) -> bool {
   249     pub fn has_sparse(&self) -> bool {
   275 
   284 
   276     fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> {
   285     fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> {
   277         let dirstate = self.dirstate_file_contents()?;
   286         let dirstate = self.dirstate_file_contents()?;
   278         let parents = if dirstate.is_empty() {
   287         let parents = if dirstate.is_empty() {
   279             DirstateParents::NULL
   288             DirstateParents::NULL
   280         } else if self.has_dirstate_v2() {
   289         } else if self.use_dirstate_v2() {
   281             let docket =
   290             let docket =
   282                 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
   291                 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
   283             docket.parents()
   292             docket.parents()
   284         } else {
   293         } else {
   285             *crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?
   294             *crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?
   294     /// Namely, the inode, data file uuid and the data size.
   303     /// Namely, the inode, data file uuid and the data size.
   295     fn get_dirstate_data_file_integrity(
   304     fn get_dirstate_data_file_integrity(
   296         &self,
   305         &self,
   297     ) -> Result<DirstateMapIdentity, HgError> {
   306     ) -> Result<DirstateMapIdentity, HgError> {
   298         assert!(
   307         assert!(
   299             self.has_dirstate_v2(),
   308             self.use_dirstate_v2(),
   300             "accessing dirstate data file ID without dirstate-v2"
   309             "accessing dirstate data file ID without dirstate-v2"
   301         );
   310         );
   302         // Get the identity before the contents since we could have a race
   311         // Get the identity before the contents since we could have a race
   303         // between the two. Having an identity that is too old is fine, but
   312         // between the two. Having an identity that is too old is fine, but
   304         // one that is younger than the content change is bad.
   313         // one that is younger than the content change is bad.
   314             Ok((identity, Some(docket.uuid.to_owned()), docket.data_size()))
   323             Ok((identity, Some(docket.uuid.to_owned()), docket.data_size()))
   315         }
   324         }
   316     }
   325     }
   317 
   326 
   318     fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> {
   327     fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> {
   319         if self.has_dirstate_v2() {
   328         if self.use_dirstate_v2() {
   320             // The v2 dirstate is split into a docket and a data file.
   329             // The v2 dirstate is split into a docket and a data file.
   321             // Since we don't always take the `wlock` to read it
   330             // Since we don't always take the `wlock` to read it
   322             // (like in `hg status`), it is susceptible to races.
   331             // (like in `hg status`), it is susceptible to races.
   323             // A simple retry method should be enough since full rewrites
   332             // A simple retry method should be enough since full rewrites
   324             // only happen when too much garbage data is present and
   333             // only happen when too much garbage data is present and
   548     pub fn write_dirstate(&self) -> Result<(), DirstateError> {
   557     pub fn write_dirstate(&self) -> Result<(), DirstateError> {
   549         let map = self.dirstate_map()?;
   558         let map = self.dirstate_map()?;
   550         // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if
   559         // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if
   551         // it’s unset
   560         // it’s unset
   552         let parents = self.dirstate_parents()?;
   561         let parents = self.dirstate_parents()?;
   553         let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() {
   562         let (packed_dirstate, old_uuid_to_remove) = if self.use_dirstate_v2() {
   554             let (identity, uuid, data_size) =
   563             let (identity, uuid, data_size) =
   555                 self.get_dirstate_data_file_integrity()?;
   564                 self.get_dirstate_data_file_integrity()?;
   556             let identity_changed = identity != map.old_identity();
   565             let identity_changed = identity != map.old_identity();
   557             let uuid_changed = uuid.as_deref() != map.old_uuid();
   566             let uuid_changed = uuid.as_deref() != map.old_uuid();
   558             let data_length_changed = data_size != map.old_data_size();
   567             let data_length_changed = data_size != map.old_data_size();