diff -r cfd270d83169 -r dd6b67d5c256 rust/hg-core/src/dirstate_tree/dirstate_map.rs --- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs Tue Apr 05 10:55:27 2022 +0200 +++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs Tue Apr 05 10:55:28 2022 +0200 @@ -725,10 +725,11 @@ impl OwningDirstateMap { pub fn clear(&mut self) { - let map = self.get_map_mut(); - map.root = Default::default(); - map.nodes_with_entry_count = 0; - map.nodes_with_copy_source_count = 0; + self.with_dmap_mut(|map| { + map.root = Default::default(); + map.nodes_with_entry_count = 0; + map.nodes_with_copy_source_count = 0; + }); } pub fn set_entry( @@ -736,9 +737,10 @@ filename: &HgPath, entry: DirstateEntry, ) -> Result<(), DirstateV2ParseError> { - let map = self.get_map_mut(); - map.get_or_insert(&filename)?.data = NodeData::Entry(entry); - Ok(()) + self.with_dmap_mut(|map| { + map.get_or_insert(&filename)?.data = NodeData::Entry(entry); + Ok(()) + }) } pub fn add_file( @@ -747,8 +749,9 @@ entry: DirstateEntry, ) -> Result<(), DirstateError> { let old_state = self.get(filename)?.map(|e| e.state()); - let map = self.get_map_mut(); - Ok(map.add_or_remove_file(filename, old_state, entry)?) + self.with_dmap_mut(|map| { + Ok(map.add_or_remove_file(filename, old_state, entry)?) + }) } pub fn remove_file( @@ -779,9 +782,10 @@ if size == 0 { self.copy_map_remove(filename)?; } - let map = self.get_map_mut(); - let entry = DirstateEntry::new_removed(size); - Ok(map.add_or_remove_file(filename, old_state, entry)?) + self.with_dmap_mut(|map| { + let entry = DirstateEntry::new_removed(size); + Ok(map.add_or_remove_file(filename, old_state, entry)?) + }) } pub fn drop_entry_and_copy_source( @@ -791,7 +795,6 @@ let was_tracked = self .get(filename)? .map_or(false, |e| e.state().is_tracked()); - let map = self.get_map_mut(); struct Dropped { was_tracked: bool, had_entry: bool, @@ -878,52 +881,56 @@ Ok(Some((dropped, remove))) } - if let Some((dropped, _removed)) = recur( - map.on_disk, - &mut map.unreachable_bytes, - &mut map.root, - filename, - )? { - if dropped.had_entry { - map.nodes_with_entry_count -= 1 + self.with_dmap_mut(|map| { + if let Some((dropped, _removed)) = recur( + map.on_disk, + &mut map.unreachable_bytes, + &mut map.root, + filename, + )? { + if dropped.had_entry { + map.nodes_with_entry_count -= 1 + } + if dropped.had_copy_source { + map.nodes_with_copy_source_count -= 1 + } + } else { + debug_assert!(!was_tracked); } - if dropped.had_copy_source { - map.nodes_with_copy_source_count -= 1 - } - } else { - debug_assert!(!was_tracked); - } - Ok(()) + Ok(()) + }) } pub fn has_tracked_dir( &mut self, directory: &HgPath, ) -> Result { - let map = self.get_map_mut(); - if let Some(node) = map.get_node(directory)? { - // A node without a `DirstateEntry` was created to hold child - // nodes, and is therefore a directory. - let state = node.state()?; - Ok(state.is_none() && node.tracked_descendants_count() > 0) - } else { - Ok(false) - } + self.with_dmap_mut(|map| { + if let Some(node) = map.get_node(directory)? { + // A node without a `DirstateEntry` was created to hold child + // nodes, and is therefore a directory. + let state = node.state()?; + Ok(state.is_none() && node.tracked_descendants_count() > 0) + } else { + Ok(false) + } + }) } pub fn has_dir( &mut self, directory: &HgPath, ) -> Result { - let map = self.get_map_mut(); - if let Some(node) = map.get_node(directory)? { - // A node without a `DirstateEntry` was created to hold child - // nodes, and is therefore a directory. - let state = node.state()?; - Ok(state.is_none() && node.descendants_with_entry_count() > 0) - } else { - Ok(false) - } + self.with_dmap_mut(|map| { + if let Some(node) = map.get_node(directory)? { + // A node without a `DirstateEntry` was created to hold child + // nodes, and is therefore a directory. + let state = node.state()?; + Ok(state.is_none() && node.descendants_with_entry_count() > 0) + } else { + Ok(false) + } + }) } #[timed] @@ -975,16 +982,29 @@ on_disk::write(map, can_append) } - pub fn status<'a>( - &'a mut self, - matcher: &'a (dyn Matcher + Sync), + /// `callback` allows the caller to process and do something with the + /// results of the status. This is needed to do so efficiently (i.e. + /// without cloning the `DirstateStatus` object with its paths) because + /// we need to borrow from `Self`. + pub fn with_status( + &mut self, + matcher: &(dyn Matcher + Sync), root_dir: PathBuf, ignore_files: Vec, options: StatusOptions, - ) -> Result<(DirstateStatus<'a>, Vec), StatusError> - { - let map = self.get_map_mut(); - super::status::status(map, matcher, root_dir, ignore_files, options) + callback: impl for<'r> FnOnce( + Result<(DirstateStatus<'r>, Vec), StatusError>, + ) -> R, + ) -> R { + self.with_dmap_mut(|map| { + callback(super::status::status( + map, + matcher, + root_dir, + ignore_files, + options, + )) + }) } pub fn copy_map_len(&self) -> usize { @@ -1032,22 +1052,23 @@ &mut self, key: &HgPath, ) -> Result, DirstateV2ParseError> { - let map = self.get_map_mut(); - let count = &mut map.nodes_with_copy_source_count; - let unreachable_bytes = &mut map.unreachable_bytes; - Ok(DirstateMap::get_node_mut( - map.on_disk, - unreachable_bytes, - &mut map.root, - key, - )? - .and_then(|node| { - if let Some(source) = &node.copy_source { - *count -= 1; - DirstateMap::count_dropped_path(unreachable_bytes, source); - } - node.copy_source.take().map(Cow::into_owned) - })) + self.with_dmap_mut(|map| { + let count = &mut map.nodes_with_copy_source_count; + let unreachable_bytes = &mut map.unreachable_bytes; + Ok(DirstateMap::get_node_mut( + map.on_disk, + unreachable_bytes, + &mut map.root, + key, + )? + .and_then(|node| { + if let Some(source) = &node.copy_source { + *count -= 1; + DirstateMap::count_dropped_path(unreachable_bytes, source); + } + node.copy_source.take().map(Cow::into_owned) + })) + }) } pub fn copy_map_insert( @@ -1055,19 +1076,20 @@ key: HgPathBuf, value: HgPathBuf, ) -> Result, DirstateV2ParseError> { - let map = self.get_map_mut(); - let node = DirstateMap::get_or_insert_node( - map.on_disk, - &mut map.unreachable_bytes, - &mut map.root, - &key, - WithBasename::to_cow_owned, - |_ancestor| {}, - )?; - if node.copy_source.is_none() { - map.nodes_with_copy_source_count += 1 - } - Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) + self.with_dmap_mut(|map| { + let node = DirstateMap::get_or_insert_node( + map.on_disk, + &mut map.unreachable_bytes, + &mut map.root, + &key, + WithBasename::to_cow_owned, + |_ancestor| {}, + )?; + if node.copy_source.is_none() { + map.nodes_with_copy_source_count += 1 + } + Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) + }) } pub fn len(&self) -> usize { @@ -1115,7 +1137,7 @@ >, DirstateError, > { - let map = self.get_map_mut(); + let map = self.get_map(); let on_disk = map.on_disk; Ok(Box::new(filter_map_results( map.iter_nodes(),