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) { |