comparison rust/hg-core/src/repo.rs @ 50658:1e2c6cda2309 stable

rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2` It is closer to the right semantics. I added a docstring to better explain the reasonning. In the next patch(es), I will address the underlying issue of finding the "wrong" version of the dirstate on disk.
author Raphaël Gomès <rgomes@octobus.net>
date Mon, 05 Jun 2023 16:30:25 +0200
parents a6b8b1ab9116
children bf16ef96defe
comparison
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();