##// END OF EJS Templates
dirstate-tree: Refactor DirstateMap::drop_file to be recursive...
Simon Sapin -
r47963:1249eb9c default
parent child Browse files
Show More
@@ -153,19 +153,6 b" impl<'on_disk> DirstateMap<'on_disk> {"
153 153 root: &'tree mut ChildNodes<'on_disk>,
154 154 path: &HgPath,
155 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 156 let mut children = root;
170 157 let mut components = path.components();
171 158 let mut component =
@@ -173,7 +160,6 b" impl<'on_disk> DirstateMap<'on_disk> {"
173 160 loop {
174 161 let child = children.get_mut(component)?;
175 162 if let Some(next_component) = components.next() {
176 each_ancestor(child);
177 163 component = next_component;
178 164 children = &mut child.children;
179 165 } else {
@@ -369,34 +355,47 b" impl<'on_disk> super::dispatch::Dirstate"
369 355 filename: &HgPath,
370 356 old_state: EntryState,
371 357 ) -> Result<bool, DirstateMapError> {
372 let was_tracked = old_state.is_tracked();
373 if let Some(node) = Self::get_node_mut_tracing_ancestors(
374 &mut self.root,
375 filename,
376 |ancestor| {
377 if was_tracked {
378 ancestor.tracked_descendants_count -= 1
358 struct Dropped {
359 was_tracked: bool,
360 had_entry: bool,
361 had_copy_source: bool,
379 362 }
380 },
381 ) {
382 let had_entry = node.entry.is_some();
383 let had_copy_source = node.copy_source.is_some();
384
363 fn recur(nodes: &mut ChildNodes, path: &HgPath) -> Option<Dropped> {
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;
372 }
373 } else {
374 dropped = Dropped {
375 was_tracked: node
376 .entry
377 .as_ref()
378 .map_or(false, |entry| entry.state.is_tracked()),
379 had_entry: node.entry.take().is_some(),
380 had_copy_source: node.copy_source.take().is_some(),
381 };
385 382 // TODO: this leaves in the tree a "non-file" node. Should we
386 383 // remove the node instead, together with ancestor nodes for
387 384 // directories that become empty?
388 node.entry = None;
389 node.copy_source = None;
385 }
386 Some(dropped)
387 }
390 388
391 if had_entry {
389 if let Some(dropped) = recur(&mut self.root, filename) {
390 if dropped.had_entry {
392 391 self.nodes_with_entry_count -= 1
393 392 }
394 if had_copy_source {
393 if dropped.had_copy_source {
395 394 self.nodes_with_copy_source_count -= 1
396 395 }
397 Ok(had_entry)
396 Ok(dropped.had_entry)
398 397 } else {
399 assert!(!was_tracked);
398 debug_assert!(!old_state.is_tracked());
400 399 Ok(false)
401 400 }
402 401 }
@@ -5,6 +5,7 b''
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 use crate::utils::SliceExt;
8 9 use std::borrow::Borrow;
9 10 use std::borrow::Cow;
10 11 use std::convert::TryFrom;
@@ -232,6 +233,15 b' impl HgPath {'
232 233 self.inner.split(|&byte| byte == b'/').map(HgPath::new)
233 234 }
234 235
236 /// Returns the first (that is "root-most") slash-separated component of
237 /// the path, and the rest after the first slash if there is one.
238 pub fn split_first_component(&self) -> (&HgPath, Option<&HgPath>) {
239 match self.inner.split_2(b'/') {
240 Some((a, b)) => (HgPath::new(a), Some(HgPath::new(b))),
241 None => (self, None),
242 }
243 }
244
235 245 pub fn parent(&self) -> &Self {
236 246 let inner = self.as_bytes();
237 247 HgPath::new(match inner.iter().rposition(|b| *b == b'/') {
General Comments 0
You need to be logged in to leave comments. Login now