Show More
@@ -153,19 +153,6 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||||
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 = | |
@@ -173,7 +160,6 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||||
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 { | |
@@ -369,34 +355,47 b" impl<'on_disk> super::dispatch::Dirstate" | |||||
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 |
|
|
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 | |
|
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 | }; | |||
|
382 | // TODO: this leaves in the tree a "non-file" node. Should we | |||
|
383 | // remove the node instead, together with ancestor nodes for | |||
|
384 | // directories that become empty? | |||
|
385 | } | |||
|
386 | Some(dropped) | |||
|
387 | } | |||
384 |
|
388 | |||
385 | // TODO: this leaves in the tree a "non-file" node. Should we |
|
389 | if let Some(dropped) = recur(&mut self.root, filename) { | |
386 | // remove the node instead, together with ancestor nodes for |
|
390 | if dropped.had_entry { | |
387 | // directories that become empty? |
|
|||
388 | node.entry = None; |
|
|||
389 | node.copy_source = None; |
|
|||
390 |
|
||||
391 | if 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!(! |
|
398 | debug_assert!(!old_state.is_tracked()); | |
400 | Ok(false) |
|
399 | Ok(false) | |
401 | } |
|
400 | } | |
402 | } |
|
401 | } |
@@ -5,6 +5,7 b'' | |||||
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
6 | // GNU General Public License version 2 or any later version. |
|
6 | // GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
|
8 | use crate::utils::SliceExt; | |||
8 | use std::borrow::Borrow; |
|
9 | use std::borrow::Borrow; | |
9 | use std::borrow::Cow; |
|
10 | use std::borrow::Cow; | |
10 | use std::convert::TryFrom; |
|
11 | use std::convert::TryFrom; | |
@@ -232,6 +233,15 b' impl HgPath {' | |||||
232 | self.inner.split(|&byte| byte == b'/').map(HgPath::new) |
|
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 | pub fn parent(&self) -> &Self { |
|
245 | pub fn parent(&self) -> &Self { | |
236 | let inner = self.as_bytes(); |
|
246 | let inner = self.as_bytes(); | |
237 | HgPath::new(match inner.iter().rposition(|b| *b == b'/') { |
|
247 | HgPath::new(match inner.iter().rposition(|b| *b == b'/') { |
General Comments 0
You need to be logged in to leave comments.
Login now