comparison rust/hg-core/src/repo.rs @ 49146:802e2c25dab8 stable

rust-dirstate-v2: clean up previous data file after the docket is written This was overlooked before and caused many data files to keep living forever. We could potentially consider adding a random cleanup of them in case they slipped through one day. Differential Revision: https://phab.mercurial-scm.org/D12581
author Raphaël Gomès <rgomes@octobus.net>
date Thu, 21 Apr 2022 15:10:57 +0200
parents dd2503a63d33
children 10b9f11daf15 f2ef6a4f918f
comparison
equal deleted inserted replaced
49145:dd2503a63d33 49146:802e2c25dab8
432 pub fn write_dirstate(&self) -> Result<(), DirstateError> { 432 pub fn write_dirstate(&self) -> Result<(), DirstateError> {
433 let map = self.dirstate_map()?; 433 let map = self.dirstate_map()?;
434 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if 434 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if
435 // it’s unset 435 // it’s unset
436 let parents = self.dirstate_parents()?; 436 let parents = self.dirstate_parents()?;
437 let packed_dirstate = if self.has_dirstate_v2() { 437 let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() {
438 let uuid = self.dirstate_data_file_uuid.get_or_init(self)?; 438 let uuid = self.dirstate_data_file_uuid.get_or_init(self)?;
439 let mut uuid = uuid.as_ref(); 439 let mut uuid = uuid.as_ref();
440 let can_append = uuid.is_some(); 440 let can_append = uuid.is_some();
441 let (data, tree_metadata, append, old_data_size) = 441 let (data, tree_metadata, append, old_data_size) =
442 map.pack_v2(can_append)?; 442 map.pack_v2(can_append)?;
443 if !append { 443 if !append {
444 uuid = None 444 uuid = None
445 } 445 }
446 let uuid = if let Some(uuid) = uuid { 446 let (uuid, old_uuid) = if let Some(uuid) = uuid {
447 std::str::from_utf8(uuid) 447 let as_str = std::str::from_utf8(uuid)
448 .map_err(|_| { 448 .map_err(|_| {
449 HgError::corrupted("non-UTF-8 dirstate data file ID") 449 HgError::corrupted("non-UTF-8 dirstate data file ID")
450 })? 450 })?
451 .to_owned() 451 .to_owned();
452 let old_uuid_to_remove = Some(as_str.to_owned());
453 (as_str, old_uuid_to_remove)
452 } else { 454 } else {
453 DirstateDocket::new_uid() 455 (DirstateDocket::new_uid(), None)
454 }; 456 };
455 let data_filename = format!("dirstate.{}", uuid); 457 let data_filename = format!("dirstate.{}", uuid);
456 let data_filename = self.hg_vfs().join(data_filename); 458 let data_filename = self.hg_vfs().join(data_filename);
457 let mut options = std::fs::OpenOptions::new(); 459 let mut options = std::fs::OpenOptions::new();
458 if append { 460 if append {
478 // TODO: use https://doc.rust-lang.org/std/io/trait.Seek.html#method.stream_position when we require Rust 1.51+ 480 // TODO: use https://doc.rust-lang.org/std/io/trait.Seek.html#method.stream_position when we require Rust 1.51+
479 file.seek(SeekFrom::Current(0)) 481 file.seek(SeekFrom::Current(0))
480 } 482 }
481 })() 483 })()
482 .when_writing_file(&data_filename)?; 484 .when_writing_file(&data_filename)?;
483 DirstateDocket::serialize( 485
486 let packed_dirstate = DirstateDocket::serialize(
484 parents, 487 parents,
485 tree_metadata, 488 tree_metadata,
486 data_size, 489 data_size,
487 uuid.as_bytes(), 490 uuid.as_bytes(),
488 ) 491 )
489 .map_err(|_: std::num::TryFromIntError| { 492 .map_err(|_: std::num::TryFromIntError| {
490 HgError::corrupted("overflow in dirstate docket serialization") 493 HgError::corrupted("overflow in dirstate docket serialization")
491 })? 494 })?;
492 } else { 495
493 map.pack_v1(parents)? 496 (packed_dirstate, old_uuid)
497 } else {
498 (map.pack_v1(parents)?, None)
494 }; 499 };
495 self.hg_vfs().atomic_write("dirstate", &packed_dirstate)?; 500
501 let vfs = self.hg_vfs();
502 vfs.atomic_write("dirstate", &packed_dirstate)?;
503 if let Some(uuid) = old_uuid_to_remove {
504 // Remove the old data file after the new docket pointing to the
505 // new data file was written.
506 vfs.remove_file(format!("dirstate.{}", uuid))?;
507 }
496 Ok(()) 508 Ok(())
497 } 509 }
498 } 510 }
499 511
500 /// Lazily-initialized component of `Repo` with interior mutability 512 /// Lazily-initialized component of `Repo` with interior mutability