comparison rust/hg-core/src/dirstate_tree/dirstate_map.rs @ 49005:12adf8c695ed

merge: stable into default
author Raphaël Gomès <rgomes@octobus.net>
date Tue, 05 Apr 2022 11:09:03 +0200
parents 11c0411bf4e2 ce919b1a1063
children a85c123c625a
comparison
equal deleted inserted replaced
48997:20c6c9e43397 49005:12adf8c695ed
721 }) 721 })
722 } 722 }
723 723
724 impl OwningDirstateMap { 724 impl OwningDirstateMap {
725 pub fn clear(&mut self) { 725 pub fn clear(&mut self) {
726 let map = self.get_map_mut(); 726 self.with_dmap_mut(|map| {
727 map.root = Default::default(); 727 map.root = Default::default();
728 map.nodes_with_entry_count = 0; 728 map.nodes_with_entry_count = 0;
729 map.nodes_with_copy_source_count = 0; 729 map.nodes_with_copy_source_count = 0;
730 });
730 } 731 }
731 732
732 pub fn set_entry( 733 pub fn set_entry(
733 &mut self, 734 &mut self,
734 filename: &HgPath, 735 filename: &HgPath,
735 entry: DirstateEntry, 736 entry: DirstateEntry,
736 ) -> Result<(), DirstateV2ParseError> { 737 ) -> Result<(), DirstateV2ParseError> {
737 let map = self.get_map_mut(); 738 self.with_dmap_mut(|map| {
738 map.get_or_insert(&filename)?.data = NodeData::Entry(entry); 739 map.get_or_insert(&filename)?.data = NodeData::Entry(entry);
739 Ok(()) 740 Ok(())
741 })
740 } 742 }
741 743
742 pub fn add_file( 744 pub fn add_file(
743 &mut self, 745 &mut self,
744 filename: &HgPath, 746 filename: &HgPath,
745 entry: DirstateEntry, 747 entry: DirstateEntry,
746 ) -> Result<(), DirstateError> { 748 ) -> Result<(), DirstateError> {
747 let old_state = self.get(filename)?.map(|e| e.state()); 749 let old_state = self.get(filename)?.map(|e| e.state());
748 let map = self.get_map_mut(); 750 self.with_dmap_mut(|map| {
749 Ok(map.add_or_remove_file(filename, old_state, entry)?) 751 Ok(map.add_or_remove_file(filename, old_state, entry)?)
752 })
750 } 753 }
751 754
752 pub fn remove_file( 755 pub fn remove_file(
753 &mut self, 756 &mut self,
754 filename: &HgPath, 757 filename: &HgPath,
775 } 778 }
776 } 779 }
777 if size == 0 { 780 if size == 0 {
778 self.copy_map_remove(filename)?; 781 self.copy_map_remove(filename)?;
779 } 782 }
780 let map = self.get_map_mut(); 783 self.with_dmap_mut(|map| {
781 let entry = DirstateEntry::new_removed(size); 784 let entry = DirstateEntry::new_removed(size);
782 Ok(map.add_or_remove_file(filename, old_state, entry)?) 785 Ok(map.add_or_remove_file(filename, old_state, entry)?)
786 })
783 } 787 }
784 788
785 pub fn drop_entry_and_copy_source( 789 pub fn drop_entry_and_copy_source(
786 &mut self, 790 &mut self,
787 filename: &HgPath, 791 filename: &HgPath,
788 ) -> Result<(), DirstateError> { 792 ) -> Result<(), DirstateError> {
789 let was_tracked = self 793 let was_tracked = self
790 .get(filename)? 794 .get(filename)?
791 .map_or(false, |e| e.state().is_tracked()); 795 .map_or(false, |e| e.state().is_tracked());
792 let map = self.get_map_mut();
793 struct Dropped { 796 struct Dropped {
794 was_tracked: bool, 797 was_tracked: bool,
795 had_entry: bool, 798 had_entry: bool,
796 had_copy_source: bool, 799 had_copy_source: bool,
797 } 800 }
824 &mut node.children, 827 &mut node.children,
825 rest, 828 rest,
826 )? { 829 )? {
827 dropped = d; 830 dropped = d;
828 if dropped.had_entry { 831 if dropped.had_entry {
829 node.descendants_with_entry_count -= 1; 832 node.descendants_with_entry_count = node
833 .descendants_with_entry_count
834 .checked_sub(1)
835 .expect(
836 "descendants_with_entry_count should be >= 0",
837 );
830 } 838 }
831 if dropped.was_tracked { 839 if dropped.was_tracked {
832 node.tracked_descendants_count -= 1; 840 node.tracked_descendants_count = node
841 .tracked_descendants_count
842 .checked_sub(1)
843 .expect(
844 "tracked_descendants_count should be >= 0",
845 );
833 } 846 }
834 847
835 // Directory caches must be invalidated when removing a 848 // Directory caches must be invalidated when removing a
836 // child node 849 // child node
837 if removed { 850 if removed {
841 } 854 }
842 } else { 855 } else {
843 return Ok(None); 856 return Ok(None);
844 } 857 }
845 } else { 858 } else {
846 let had_entry = node.data.has_entry(); 859 let entry = node.data.as_entry();
860 let was_tracked = entry.map_or(false, |entry| entry.tracked());
861 let had_entry = entry.is_some();
847 if had_entry { 862 if had_entry {
848 node.data = NodeData::None 863 node.data = NodeData::None
849 } 864 }
865 let mut had_copy_source = false;
850 if let Some(source) = &node.copy_source { 866 if let Some(source) = &node.copy_source {
851 DirstateMap::count_dropped_path(unreachable_bytes, source); 867 DirstateMap::count_dropped_path(unreachable_bytes, source);
868 had_copy_source = true;
852 node.copy_source = None 869 node.copy_source = None
853 } 870 }
854 dropped = Dropped { 871 dropped = Dropped {
855 was_tracked: node 872 was_tracked,
856 .data
857 .as_entry()
858 .map_or(false, |entry| entry.state().is_tracked()),
859 had_entry, 873 had_entry,
860 had_copy_source: node.copy_source.take().is_some(), 874 had_copy_source,
861 }; 875 };
862 } 876 }
863 // After recursion, for both leaf (rest_of_path is None) nodes and 877 // After recursion, for both leaf (rest_of_path is None) nodes and
864 // parent nodes, remove a node if it just became empty. 878 // parent nodes, remove a node if it just became empty.
865 let remove = !node.data.has_entry() 879 let remove = !node.data.has_entry()
874 ) 888 )
875 } 889 }
876 Ok(Some((dropped, remove))) 890 Ok(Some((dropped, remove)))
877 } 891 }
878 892
879 if let Some((dropped, _removed)) = recur( 893 self.with_dmap_mut(|map| {
880 map.on_disk, 894 if let Some((dropped, _removed)) = recur(
881 &mut map.unreachable_bytes, 895 map.on_disk,
882 &mut map.root, 896 &mut map.unreachable_bytes,
883 filename, 897 &mut map.root,
884 )? { 898 filename,
885 if dropped.had_entry { 899 )? {
886 map.nodes_with_entry_count -= 1 900 if dropped.had_entry {
887 } 901 map.nodes_with_entry_count = map
888 if dropped.had_copy_source { 902 .nodes_with_entry_count
889 map.nodes_with_copy_source_count -= 1 903 .checked_sub(1)
890 } 904 .expect("nodes_with_entry_count should be >= 0");
891 } else { 905 }
892 debug_assert!(!was_tracked); 906 if dropped.had_copy_source {
893 } 907 map.nodes_with_copy_source_count = map
894 Ok(()) 908 .nodes_with_copy_source_count
909 .checked_sub(1)
910 .expect("nodes_with_copy_source_count should be >= 0");
911 }
912 } else {
913 debug_assert!(!was_tracked);
914 }
915 Ok(())
916 })
895 } 917 }
896 918
897 pub fn has_tracked_dir( 919 pub fn has_tracked_dir(
898 &mut self, 920 &mut self,
899 directory: &HgPath, 921 directory: &HgPath,
900 ) -> Result<bool, DirstateError> { 922 ) -> Result<bool, DirstateError> {
901 let map = self.get_map_mut(); 923 self.with_dmap_mut(|map| {
902 if let Some(node) = map.get_node(directory)? { 924 if let Some(node) = map.get_node(directory)? {
903 // A node without a `DirstateEntry` was created to hold child 925 // A node without a `DirstateEntry` was created to hold child
904 // nodes, and is therefore a directory. 926 // nodes, and is therefore a directory.
905 let state = node.state()?; 927 let state = node.state()?;
906 Ok(state.is_none() && node.tracked_descendants_count() > 0) 928 Ok(state.is_none() && node.tracked_descendants_count() > 0)
907 } else { 929 } else {
908 Ok(false) 930 Ok(false)
909 } 931 }
932 })
910 } 933 }
911 934
912 pub fn has_dir( 935 pub fn has_dir(
913 &mut self, 936 &mut self,
914 directory: &HgPath, 937 directory: &HgPath,
915 ) -> Result<bool, DirstateError> { 938 ) -> Result<bool, DirstateError> {
916 let map = self.get_map_mut(); 939 self.with_dmap_mut(|map| {
917 if let Some(node) = map.get_node(directory)? { 940 if let Some(node) = map.get_node(directory)? {
918 // A node without a `DirstateEntry` was created to hold child 941 // A node without a `DirstateEntry` was created to hold child
919 // nodes, and is therefore a directory. 942 // nodes, and is therefore a directory.
920 let state = node.state()?; 943 let state = node.state()?;
921 Ok(state.is_none() && node.descendants_with_entry_count() > 0) 944 Ok(state.is_none() && node.descendants_with_entry_count() > 0)
922 } else { 945 } else {
923 Ok(false) 946 Ok(false)
924 } 947 }
948 })
925 } 949 }
926 950
927 #[timed] 951 #[timed]
928 pub fn pack_v1( 952 pub fn pack_v1(
929 &self, 953 &self,
971 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> { 995 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> {
972 let map = self.get_map(); 996 let map = self.get_map();
973 on_disk::write(map, can_append) 997 on_disk::write(map, can_append)
974 } 998 }
975 999
976 pub fn status<'a>( 1000 /// `callback` allows the caller to process and do something with the
977 &'a mut self, 1001 /// results of the status. This is needed to do so efficiently (i.e.
978 matcher: &'a (dyn Matcher + Sync), 1002 /// without cloning the `DirstateStatus` object with its paths) because
1003 /// we need to borrow from `Self`.
1004 pub fn with_status<R>(
1005 &mut self,
1006 matcher: &(dyn Matcher + Sync),
979 root_dir: PathBuf, 1007 root_dir: PathBuf,
980 ignore_files: Vec<PathBuf>, 1008 ignore_files: Vec<PathBuf>,
981 options: StatusOptions, 1009 options: StatusOptions,
982 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError> 1010 callback: impl for<'r> FnOnce(
983 { 1011 Result<(DirstateStatus<'r>, Vec<PatternFileWarning>), StatusError>,
984 let map = self.get_map_mut(); 1012 ) -> R,
985 super::status::status(map, matcher, root_dir, ignore_files, options) 1013 ) -> R {
1014 self.with_dmap_mut(|map| {
1015 callback(super::status::status(
1016 map,
1017 matcher,
1018 root_dir,
1019 ignore_files,
1020 options,
1021 ))
1022 })
986 } 1023 }
987 1024
988 pub fn copy_map_len(&self) -> usize { 1025 pub fn copy_map_len(&self) -> usize {
989 let map = self.get_map(); 1026 let map = self.get_map();
990 map.nodes_with_copy_source_count as usize 1027 map.nodes_with_copy_source_count as usize
1028 1065
1029 pub fn copy_map_remove( 1066 pub fn copy_map_remove(
1030 &mut self, 1067 &mut self,
1031 key: &HgPath, 1068 key: &HgPath,
1032 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { 1069 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1033 let map = self.get_map_mut(); 1070 self.with_dmap_mut(|map| {
1034 let count = &mut map.nodes_with_copy_source_count; 1071 let count = &mut map.nodes_with_copy_source_count;
1035 let unreachable_bytes = &mut map.unreachable_bytes; 1072 let unreachable_bytes = &mut map.unreachable_bytes;
1036 Ok(DirstateMap::get_node_mut( 1073 Ok(DirstateMap::get_node_mut(
1037 map.on_disk, 1074 map.on_disk,
1038 unreachable_bytes, 1075 unreachable_bytes,
1039 &mut map.root, 1076 &mut map.root,
1040 key, 1077 key,
1041 )? 1078 )?
1042 .and_then(|node| { 1079 .and_then(|node| {
1043 if let Some(source) = &node.copy_source { 1080 if let Some(source) = &node.copy_source {
1044 *count -= 1; 1081 *count -= 1;
1045 DirstateMap::count_dropped_path(unreachable_bytes, source); 1082 DirstateMap::count_dropped_path(unreachable_bytes, source);
1046 } 1083 }
1047 node.copy_source.take().map(Cow::into_owned) 1084 node.copy_source.take().map(Cow::into_owned)
1048 })) 1085 }))
1086 })
1049 } 1087 }
1050 1088
1051 pub fn copy_map_insert( 1089 pub fn copy_map_insert(
1052 &mut self, 1090 &mut self,
1053 key: HgPathBuf, 1091 key: HgPathBuf,
1054 value: HgPathBuf, 1092 value: HgPathBuf,
1055 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { 1093 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1056 let map = self.get_map_mut(); 1094 self.with_dmap_mut(|map| {
1057 let node = DirstateMap::get_or_insert_node( 1095 let node = DirstateMap::get_or_insert_node(
1058 map.on_disk, 1096 map.on_disk,
1059 &mut map.unreachable_bytes, 1097 &mut map.unreachable_bytes,
1060 &mut map.root, 1098 &mut map.root,
1061 &key, 1099 &key,
1062 WithBasename::to_cow_owned, 1100 WithBasename::to_cow_owned,
1063 |_ancestor| {}, 1101 |_ancestor| {},
1064 )?; 1102 )?;
1065 if node.copy_source.is_none() { 1103 if node.copy_source.is_none() {
1066 map.nodes_with_copy_source_count += 1 1104 map.nodes_with_copy_source_count += 1
1067 } 1105 }
1068 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) 1106 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned))
1107 })
1069 } 1108 }
1070 1109
1071 pub fn len(&self) -> usize { 1110 pub fn len(&self) -> usize {
1072 let map = self.get_map(); 1111 let map = self.get_map();
1073 map.nodes_with_entry_count as usize 1112 map.nodes_with_entry_count as usize
1111 + Send 1150 + Send
1112 + '_, 1151 + '_,
1113 >, 1152 >,
1114 DirstateError, 1153 DirstateError,
1115 > { 1154 > {
1116 let map = self.get_map_mut(); 1155 let map = self.get_map();
1117 let on_disk = map.on_disk; 1156 let on_disk = map.on_disk;
1118 Ok(Box::new(filter_map_results( 1157 Ok(Box::new(filter_map_results(
1119 map.iter_nodes(), 1158 map.iter_nodes(),
1120 move |node| { 1159 move |node| {
1121 Ok(if node.tracked_descendants_count() > 0 { 1160 Ok(if node.tracked_descendants_count() > 0 {