Mercurial > hg
comparison rust/hg-core/src/dirstate_tree/dirstate_map.rs @ 47352:9d58e54b5966
dirstate-v2: Drop parent directory cache when removing a dirstate node
The premise of the directory cache is that the dirstate contains child nodes
for every entry that `read_dir` would return. When removing nodes, that may
not be the case anymore so the cache should be invalidated.
Differential Revision: https://phab.mercurial-scm.org/D10829
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Tue, 01 Jun 2021 16:55:59 +0200 |
parents | 3b9914b28133 |
children | 0ef8231e413f |
comparison
equal
deleted
inserted
replaced
47351:3b9914b28133 | 47352:9d58e54b5966 |
---|---|
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 |