710 struct Dropped { |
710 struct Dropped { |
711 was_tracked: bool, |
711 was_tracked: bool, |
712 had_entry: bool, |
712 had_entry: bool, |
713 had_copy_source: bool, |
713 had_copy_source: bool, |
714 } |
714 } |
|
715 |
|
716 /// If this returns `Ok(Some((dropped, removed)))`, then |
|
717 /// |
|
718 /// * `dropped` is about the leaf node that was at `filename` |
|
719 /// * `removed` is whether this particular level of recursion just |
|
720 /// removed a node in `nodes`. |
715 fn recur<'on_disk>( |
721 fn recur<'on_disk>( |
716 on_disk: &'on_disk [u8], |
722 on_disk: &'on_disk [u8], |
717 nodes: &mut ChildNodes<'on_disk>, |
723 nodes: &mut ChildNodes<'on_disk>, |
718 path: &HgPath, |
724 path: &HgPath, |
719 ) -> Result<Option<Dropped>, DirstateV2ParseError> { |
725 ) -> Result<Option<(Dropped, bool)>, DirstateV2ParseError> { |
720 let (first_path_component, rest_of_path) = |
726 let (first_path_component, rest_of_path) = |
721 path.split_first_component(); |
727 path.split_first_component(); |
722 let node = if let Some(node) = |
728 let node = if let Some(node) = |
723 nodes.make_mut(on_disk)?.get_mut(first_path_component) |
729 nodes.make_mut(on_disk)?.get_mut(first_path_component) |
724 { |
730 { |
726 } else { |
732 } else { |
727 return Ok(None); |
733 return Ok(None); |
728 }; |
734 }; |
729 let dropped; |
735 let dropped; |
730 if let Some(rest) = rest_of_path { |
736 if let Some(rest) = rest_of_path { |
731 if let Some(d) = recur(on_disk, &mut node.children, rest)? { |
737 if let Some((d, removed)) = |
|
738 recur(on_disk, &mut node.children, rest)? |
|
739 { |
732 dropped = d; |
740 dropped = d; |
733 if dropped.was_tracked { |
741 if dropped.was_tracked { |
734 node.tracked_descendants_count -= 1; |
742 node.tracked_descendants_count -= 1; |
|
743 } |
|
744 |
|
745 // Directory caches must be invalidated when removing a |
|
746 // child node |
|
747 if removed { |
|
748 if let NodeData::CachedDirectory { .. } = &node.data { |
|
749 node.data = NodeData::None |
|
750 } |
735 } |
751 } |
736 } else { |
752 } else { |
737 return Ok(None); |
753 return Ok(None); |
738 } |
754 } |
739 } else { |
755 } else { |
750 had_copy_source: node.copy_source.take().is_some(), |
766 had_copy_source: node.copy_source.take().is_some(), |
751 }; |
767 }; |
752 } |
768 } |
753 // After recursion, for both leaf (rest_of_path is None) nodes and |
769 // After recursion, for both leaf (rest_of_path is None) nodes and |
754 // parent nodes, remove a node if it just became empty. |
770 // parent nodes, remove a node if it just became empty. |
755 if !node.data.has_entry() |
771 let remove = !node.data.has_entry() |
756 && node.copy_source.is_none() |
772 && node.copy_source.is_none() |
757 && node.children.is_empty() |
773 && node.children.is_empty(); |
758 { |
774 if remove { |
759 nodes.make_mut(on_disk)?.remove(first_path_component); |
775 nodes.make_mut(on_disk)?.remove(first_path_component); |
760 } |
776 } |
761 Ok(Some(dropped)) |
777 Ok(Some((dropped, remove))) |
762 } |
778 } |
763 |
779 |
764 if let Some(dropped) = recur(self.on_disk, &mut self.root, filename)? { |
780 if let Some((dropped, _removed)) = |
|
781 recur(self.on_disk, &mut self.root, filename)? |
|
782 { |
765 if dropped.had_entry { |
783 if dropped.had_entry { |
766 self.nodes_with_entry_count -= 1 |
784 self.nodes_with_entry_count -= 1 |
767 } |
785 } |
768 if dropped.had_copy_source { |
786 if dropped.had_copy_source { |
769 self.nodes_with_copy_source_count -= 1 |
787 self.nodes_with_copy_source_count -= 1 |