Show More
@@ -66,6 +66,16 b' pub enum EntryState {' | |||
|
66 | 66 | Unknown, |
|
67 | 67 | } |
|
68 | 68 | |
|
69 | impl EntryState { | |
|
70 | pub fn is_tracked(self) -> bool { | |
|
71 | use EntryState::*; | |
|
72 | match self { | |
|
73 | Normal | Added | Merged => true, | |
|
74 | Removed | Unknown => false, | |
|
75 | } | |
|
76 | } | |
|
77 | } | |
|
78 | ||
|
69 | 79 | impl TryFrom<u8> for EntryState { |
|
70 | 80 | type Error = HgError; |
|
71 | 81 |
@@ -46,11 +46,29 b' pub struct DirstateMap {' | |||
|
46 | 46 | /// string prefix. |
|
47 | 47 | type ChildNodes = BTreeMap<WithBasename<HgPathBuf>, Node>; |
|
48 | 48 | |
|
49 | /// Represents a file or a directory | |
|
49 | 50 | #[derive(Default)] |
|
50 | 51 | struct Node { |
|
52 | /// `None` for directories | |
|
51 | 53 | entry: Option<DirstateEntry>, |
|
54 | ||
|
52 | 55 | copy_source: Option<HgPathBuf>, |
|
56 | ||
|
53 | 57 | children: ChildNodes, |
|
58 | ||
|
59 | /// How many (non-inclusive) descendants of this node are tracked files | |
|
60 | tracked_descendants_count: usize, | |
|
61 | } | |
|
62 | ||
|
63 | impl Node { | |
|
64 | /// Whether this node has a `DirstateEntry` with `.state.is_tracked()` | |
|
65 | fn is_tracked_file(&self) -> bool { | |
|
66 | if let Some(entry) = &self.entry { | |
|
67 | entry.state.is_tracked() | |
|
68 | } else { | |
|
69 | false | |
|
70 | } | |
|
71 | } | |
|
54 | 72 | } |
|
55 | 73 | |
|
56 | 74 | /// `(full_path, entry, copy_source)` |
@@ -87,18 +105,48 b' impl DirstateMap {' | |||
|
87 | 105 | } |
|
88 | 106 | } |
|
89 | 107 | |
|
108 | /// Returns a mutable reference to the node at `path` if it exists | |
|
109 | /// | |
|
90 | 110 | /// This takes `root` instead of `&mut self` so that callers can mutate |
|
91 | 111 | /// other fields while the returned borrow is still valid |
|
92 | 112 | fn get_node_mut<'tree>( |
|
93 | 113 | root: &'tree mut ChildNodes, |
|
94 | 114 | path: &HgPath, |
|
95 | 115 | ) -> Option<&'tree mut Node> { |
|
116 | Self::each_and_get(root, path, |_| {}) | |
|
117 | } | |
|
118 | ||
|
119 | /// Call `each` for each ancestor node of the one at `path` (not including | |
|
120 | /// that node itself), starting from nearest the root. | |
|
121 | /// | |
|
122 | /// Panics (possibly after some calls to `each`) if there is no node at | |
|
123 | /// `path`. | |
|
124 | fn for_each_ancestor_node<'tree>( | |
|
125 | &mut self, | |
|
126 | path: &HgPath, | |
|
127 | each: impl FnMut(&mut Node), | |
|
128 | ) { | |
|
129 | let parent = path.parent(); | |
|
130 | if !parent.is_empty() { | |
|
131 | Self::each_and_get(&mut self.root, parent, each) | |
|
132 | .expect("missing dirstate node"); | |
|
133 | } | |
|
134 | } | |
|
135 | ||
|
136 | /// Common implementation detail of `get_node_mut` and | |
|
137 | /// `for_each_ancestor_node` | |
|
138 | fn each_and_get<'tree>( | |
|
139 | root: &'tree mut ChildNodes, | |
|
140 | path: &HgPath, | |
|
141 | mut each: impl FnMut(&mut Node), | |
|
142 | ) -> Option<&'tree mut Node> { | |
|
96 | 143 | let mut children = root; |
|
97 | 144 | let mut components = path.components(); |
|
98 | 145 | let mut component = |
|
99 | 146 | components.next().expect("expected at least one components"); |
|
100 | 147 | loop { |
|
101 | 148 | let child = children.get_mut(component)?; |
|
149 | each(child); | |
|
102 | 150 | if let Some(next_component) = components.next() { |
|
103 | 151 | component = next_component; |
|
104 | 152 | children = &mut child.children; |
@@ -162,10 +210,29 b' impl DirstateMap {' | |||
|
162 | 210 | self.nodes_with_copy_source_count -= 1 |
|
163 | 211 | } |
|
164 | 212 | } |
|
213 | let tracked_count_increment = | |
|
214 | match (node.is_tracked_file(), new_entry.state.is_tracked()) { | |
|
215 | (false, true) => 1, | |
|
216 | (true, false) => -1, | |
|
217 | _ => 0, | |
|
218 | }; | |
|
219 | ||
|
165 | 220 | node.entry = Some(new_entry); |
|
166 | 221 | if let Some(source) = new_copy_source { |
|
167 | 222 | node.copy_source = source |
|
168 | 223 | } |
|
224 | // Borrow of `self.root` through `node` ends here | |
|
225 | ||
|
226 | match tracked_count_increment { | |
|
227 | 1 => self.for_each_ancestor_node(path, |node| { | |
|
228 | node.tracked_descendants_count += 1 | |
|
229 | }), | |
|
230 | // We canβt use `+= -1` because the counter is unsigned | |
|
231 | -1 => self.for_each_ancestor_node(path, |node| { | |
|
232 | node.tracked_descendants_count -= 1 | |
|
233 | }), | |
|
234 | _ => {} | |
|
235 | } | |
|
169 | 236 | } |
|
170 | 237 | |
|
171 | 238 | fn iter_nodes<'a>( |
@@ -335,16 +402,28 b' impl super::dispatch::DirstateMapMethods' | |||
|
335 | 402 | |
|
336 | 403 | fn has_tracked_dir( |
|
337 | 404 | &mut self, |
|
338 |
|
|
|
405 | directory: &HgPath, | |
|
339 | 406 | ) -> Result<bool, DirstateMapError> { |
|
340 | todo!() | |
|
407 | if let Some(node) = self.get_node(directory) { | |
|
408 | // A node without a `DirstateEntry` was created to hold child | |
|
409 | // nodes, and is therefore a directory. | |
|
410 | Ok(node.entry.is_none() && node.tracked_descendants_count > 0) | |
|
411 | } else { | |
|
412 | Ok(false) | |
|
413 | } | |
|
341 | 414 | } |
|
342 | 415 | |
|
343 | 416 | fn has_dir( |
|
344 | 417 | &mut self, |
|
345 |
|
|
|
418 | directory: &HgPath, | |
|
346 | 419 | ) -> Result<bool, DirstateMapError> { |
|
347 | todo!() | |
|
420 | if let Some(node) = self.get_node(directory) { | |
|
421 | // A node without a `DirstateEntry` was created to hold child | |
|
422 | // nodes, and is therefore a directory. | |
|
423 | Ok(node.entry.is_none()) | |
|
424 | } else { | |
|
425 | Ok(false) | |
|
426 | } | |
|
348 | 427 | } |
|
349 | 428 | |
|
350 | 429 | fn parents( |
@@ -437,11 +516,15 b' impl super::dispatch::DirstateMapMethods' | |||
|
437 | 516 | } |
|
438 | 517 | |
|
439 | 518 | fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { |
|
440 | todo!() | |
|
519 | // Do nothing, this `DirstateMap` does not a separate `all_dirs` that | |
|
520 | // needs to be recomputed | |
|
521 | Ok(()) | |
|
441 | 522 | } |
|
442 | 523 | |
|
443 | 524 | fn set_dirs(&mut self) -> Result<(), DirstateMapError> { |
|
444 | todo!() | |
|
525 | // Do nothing, this `DirstateMap` does not a separate `dirs` that needs | |
|
526 | // to be recomputed | |
|
527 | Ok(()) | |
|
445 | 528 | } |
|
446 | 529 | |
|
447 | 530 | fn status<'a>( |
General Comments 0
You need to be logged in to leave comments.
Login now