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 |
|
|
|
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!(! |
|
|
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