comparison rust/hg-core/src/dirstate_tree/dirstate_map.rs @ 47192:1249eb9cc332

dirstate-tree: Refactor DirstateMap::drop_file to be recursive It should behave the same as before. This will enable the next changeset to run code on the way "down" (in order to removing newly-empty nodes). Differential Revision: https://phab.mercurial-scm.org/D10705
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 10 May 2021 21:31:05 +0200
parents ecfe0819ada5
children 47ccab19bf9f
comparison
equal deleted inserted replaced
47191:b338d831d18c 47192:1249eb9cc332
151 /// other fields while the returned borrow is still valid 151 /// other fields while the returned borrow is still valid
152 fn get_node_mut<'tree>( 152 fn get_node_mut<'tree>(
153 root: &'tree mut ChildNodes<'on_disk>, 153 root: &'tree mut ChildNodes<'on_disk>,
154 path: &HgPath, 154 path: &HgPath,
155 ) -> Option<&'tree mut Node<'on_disk>> { 155 ) -> Option<&'tree mut Node<'on_disk>> {
156 Self::get_node_mut_tracing_ancestors(root, path, |_| {})
157 }
158
159 /// Same as `get_node_mut`, and calls `each_ancestor` for each ancestor of
160 /// the node.
161 ///
162 /// Note that `each_ancestor` may be called (with what would be ancestors)
163 /// even if it turns out there is no node at `path`.
164 fn get_node_mut_tracing_ancestors<'tree>(
165 root: &'tree mut ChildNodes<'on_disk>,
166 path: &HgPath,
167 mut each_ancestor: impl FnMut(&mut Node),
168 ) -> Option<&'tree mut Node<'on_disk>> {
169 let mut children = root; 156 let mut children = root;
170 let mut components = path.components(); 157 let mut components = path.components();
171 let mut component = 158 let mut component =
172 components.next().expect("expected at least one components"); 159 components.next().expect("expected at least one components");
173 loop { 160 loop {
174 let child = children.get_mut(component)?; 161 let child = children.get_mut(component)?;
175 if let Some(next_component) = components.next() { 162 if let Some(next_component) = components.next() {
176 each_ancestor(child);
177 component = next_component; 163 component = next_component;
178 children = &mut child.children; 164 children = &mut child.children;
179 } else { 165 } else {
180 return Some(child); 166 return Some(child);
181 } 167 }
367 fn drop_file( 353 fn drop_file(
368 &mut self, 354 &mut self,
369 filename: &HgPath, 355 filename: &HgPath,
370 old_state: EntryState, 356 old_state: EntryState,
371 ) -> Result<bool, DirstateMapError> { 357 ) -> Result<bool, DirstateMapError> {
372 let was_tracked = old_state.is_tracked(); 358 struct Dropped {
373 if let Some(node) = Self::get_node_mut_tracing_ancestors( 359 was_tracked: bool,
374 &mut self.root, 360 had_entry: bool,
375 filename, 361 had_copy_source: bool,
376 |ancestor| { 362 }
377 if was_tracked { 363 fn recur(nodes: &mut ChildNodes, path: &HgPath) -> Option<Dropped> {
378 ancestor.tracked_descendants_count -= 1 364 let (first_path_component, rest_of_path) =
365 path.split_first_component();
366 let node = nodes.get_mut(first_path_component)?;
367 let dropped;
368 if let Some(rest) = rest_of_path {
369 dropped = recur(&mut node.children, rest)?;
370 if dropped.was_tracked {
371 node.tracked_descendants_count -= 1;
379 } 372 }
380 }, 373 } else {
381 ) { 374 dropped = Dropped {
382 let had_entry = node.entry.is_some(); 375 was_tracked: node
383 let had_copy_source = node.copy_source.is_some(); 376 .entry
384 377 .as_ref()
385 // TODO: this leaves in the tree a "non-file" node. Should we 378 .map_or(false, |entry| entry.state.is_tracked()),
386 // remove the node instead, together with ancestor nodes for 379 had_entry: node.entry.take().is_some(),
387 // directories that become empty? 380 had_copy_source: node.copy_source.take().is_some(),
388 node.entry = None; 381 };
389 node.copy_source = None; 382 // TODO: this leaves in the tree a "non-file" node. Should we
390 383 // remove the node instead, together with ancestor nodes for
391 if had_entry { 384 // directories that become empty?
385 }
386 Some(dropped)
387 }
388
389 if let Some(dropped) = recur(&mut self.root, filename) {
390 if dropped.had_entry {
392 self.nodes_with_entry_count -= 1 391 self.nodes_with_entry_count -= 1
393 } 392 }
394 if had_copy_source { 393 if dropped.had_copy_source {
395 self.nodes_with_copy_source_count -= 1 394 self.nodes_with_copy_source_count -= 1
396 } 395 }
397 Ok(had_entry) 396 Ok(dropped.had_entry)
398 } else { 397 } else {
399 assert!(!was_tracked); 398 debug_assert!(!old_state.is_tracked());
400 Ok(false) 399 Ok(false)
401 } 400 }
402 } 401 }
403 402
404 fn clear_ambiguous_times(&mut self, filenames: Vec<HgPathBuf>, now: i32) { 403 fn clear_ambiguous_times(&mut self, filenames: Vec<HgPathBuf>, now: i32) {