877 } |
883 } |
878 Ok(Some((dropped, remove))) |
884 Ok(Some((dropped, remove))) |
879 } |
885 } |
880 |
886 |
881 if let Some((dropped, _removed)) = recur( |
887 if let Some((dropped, _removed)) = recur( |
882 self.on_disk, |
888 map.on_disk, |
883 &mut self.unreachable_bytes, |
889 &mut map.unreachable_bytes, |
884 &mut self.root, |
890 &mut map.root, |
885 filename, |
891 filename, |
886 )? { |
892 )? { |
887 if dropped.had_entry { |
893 if dropped.had_entry { |
888 self.nodes_with_entry_count -= 1 |
894 map.nodes_with_entry_count -= 1 |
889 } |
895 } |
890 if dropped.had_copy_source { |
896 if dropped.had_copy_source { |
891 self.nodes_with_copy_source_count -= 1 |
897 map.nodes_with_copy_source_count -= 1 |
892 } |
898 } |
893 } else { |
899 } else { |
894 debug_assert!(!was_tracked); |
900 debug_assert!(!was_tracked); |
895 } |
901 } |
896 Ok(()) |
902 Ok(()) |
897 } |
903 } |
898 |
904 |
899 fn has_tracked_dir( |
905 pub fn has_tracked_dir( |
900 &mut self, |
906 &mut self, |
901 directory: &HgPath, |
907 directory: &HgPath, |
902 ) -> Result<bool, DirstateError> { |
908 ) -> Result<bool, DirstateError> { |
903 if let Some(node) = self.get_node(directory)? { |
909 let map = self.get_map_mut(); |
|
910 if let Some(node) = map.get_node(directory)? { |
904 // A node without a `DirstateEntry` was created to hold child |
911 // A node without a `DirstateEntry` was created to hold child |
905 // nodes, and is therefore a directory. |
912 // nodes, and is therefore a directory. |
906 let state = node.state()?; |
913 let state = node.state()?; |
907 Ok(state.is_none() && node.tracked_descendants_count() > 0) |
914 Ok(state.is_none() && node.tracked_descendants_count() > 0) |
908 } else { |
915 } else { |
909 Ok(false) |
916 Ok(false) |
910 } |
917 } |
911 } |
918 } |
912 |
919 |
913 fn has_dir(&mut self, directory: &HgPath) -> Result<bool, DirstateError> { |
920 pub fn has_dir( |
914 if let Some(node) = self.get_node(directory)? { |
921 &mut self, |
|
922 directory: &HgPath, |
|
923 ) -> Result<bool, DirstateError> { |
|
924 let map = self.get_map_mut(); |
|
925 if let Some(node) = map.get_node(directory)? { |
915 // A node without a `DirstateEntry` was created to hold child |
926 // A node without a `DirstateEntry` was created to hold child |
916 // nodes, and is therefore a directory. |
927 // nodes, and is therefore a directory. |
917 let state = node.state()?; |
928 let state = node.state()?; |
918 Ok(state.is_none() && node.descendants_with_entry_count() > 0) |
929 Ok(state.is_none() && node.descendants_with_entry_count() > 0) |
919 } else { |
930 } else { |
920 Ok(false) |
931 Ok(false) |
921 } |
932 } |
922 } |
933 } |
923 |
934 |
924 #[timed] |
935 #[timed] |
925 fn pack_v1( |
936 pub fn pack_v1( |
926 &mut self, |
937 &mut self, |
927 parents: DirstateParents, |
938 parents: DirstateParents, |
928 now: Timestamp, |
939 now: Timestamp, |
929 ) -> Result<Vec<u8>, DirstateError> { |
940 ) -> Result<Vec<u8>, DirstateError> { |
|
941 let map = self.get_map_mut(); |
930 let now: i32 = now.0.try_into().expect("time overflow"); |
942 let now: i32 = now.0.try_into().expect("time overflow"); |
931 let mut ambiguous_mtimes = Vec::new(); |
943 let mut ambiguous_mtimes = Vec::new(); |
932 // Optizimation (to be measured?): pre-compute size to avoid `Vec` |
944 // Optizimation (to be measured?): pre-compute size to avoid `Vec` |
933 // reallocations |
945 // reallocations |
934 let mut size = parents.as_bytes().len(); |
946 let mut size = parents.as_bytes().len(); |
935 for node in self.iter_nodes() { |
947 for node in map.iter_nodes() { |
936 let node = node?; |
948 let node = node?; |
937 if let Some(entry) = node.entry()? { |
949 if let Some(entry) = node.entry()? { |
938 size += packed_entry_size( |
950 size += packed_entry_size( |
939 node.full_path(self.on_disk)?, |
951 node.full_path(map.on_disk)?, |
940 node.copy_source(self.on_disk)?, |
952 node.copy_source(map.on_disk)?, |
941 ); |
953 ); |
942 if entry.mtime_is_ambiguous(now) { |
954 if entry.mtime_is_ambiguous(now) { |
943 ambiguous_mtimes.push( |
955 ambiguous_mtimes.push( |
944 node.full_path_borrowed(self.on_disk)? |
956 node.full_path_borrowed(map.on_disk)? |
945 .detach_from_tree(), |
957 .detach_from_tree(), |
946 ) |
958 ) |
947 } |
959 } |
948 } |
960 } |
949 } |
961 } |
950 self.clear_known_ambiguous_mtimes(&ambiguous_mtimes)?; |
962 map.clear_known_ambiguous_mtimes(&ambiguous_mtimes)?; |
951 |
963 |
952 let mut packed = Vec::with_capacity(size); |
964 let mut packed = Vec::with_capacity(size); |
953 packed.extend(parents.as_bytes()); |
965 packed.extend(parents.as_bytes()); |
954 |
966 |
955 for node in self.iter_nodes() { |
967 for node in map.iter_nodes() { |
956 let node = node?; |
968 let node = node?; |
957 if let Some(entry) = node.entry()? { |
969 if let Some(entry) = node.entry()? { |
958 pack_entry( |
970 pack_entry( |
959 node.full_path(self.on_disk)?, |
971 node.full_path(map.on_disk)?, |
960 &entry, |
972 &entry, |
961 node.copy_source(self.on_disk)?, |
973 node.copy_source(map.on_disk)?, |
962 &mut packed, |
974 &mut packed, |
963 ); |
975 ); |
964 } |
976 } |
965 } |
977 } |
966 Ok(packed) |
978 Ok(packed) |
967 } |
979 } |
968 |
980 |
969 /// Returns new data and metadata together with whether that data should be |
981 /// Returns new data and metadata together with whether that data should be |
970 /// appended to the existing data file whose content is at |
982 /// appended to the existing data file whose content is at |
971 /// `self.on_disk` (true), instead of written to a new data file |
983 /// `map.on_disk` (true), instead of written to a new data file |
972 /// (false). |
984 /// (false). |
973 #[timed] |
985 #[timed] |
974 fn pack_v2( |
986 pub fn pack_v2( |
975 &mut self, |
987 &mut self, |
976 now: Timestamp, |
988 now: Timestamp, |
977 can_append: bool, |
989 can_append: bool, |
978 ) -> Result<(Vec<u8>, Vec<u8>, bool), DirstateError> { |
990 ) -> Result<(Vec<u8>, Vec<u8>, bool), DirstateError> { |
|
991 let map = self.get_map_mut(); |
979 // TODO: how do we want to handle this in 2038? |
992 // TODO: how do we want to handle this in 2038? |
980 let now: i32 = now.0.try_into().expect("time overflow"); |
993 let now: i32 = now.0.try_into().expect("time overflow"); |
981 let mut paths = Vec::new(); |
994 let mut paths = Vec::new(); |
982 for node in self.iter_nodes() { |
995 for node in map.iter_nodes() { |
983 let node = node?; |
996 let node = node?; |
984 if let Some(entry) = node.entry()? { |
997 if let Some(entry) = node.entry()? { |
985 if entry.mtime_is_ambiguous(now) { |
998 if entry.mtime_is_ambiguous(now) { |
986 paths.push( |
999 paths.push( |
987 node.full_path_borrowed(self.on_disk)? |
1000 node.full_path_borrowed(map.on_disk)? |
988 .detach_from_tree(), |
1001 .detach_from_tree(), |
989 ) |
1002 ) |
990 } |
1003 } |
991 } |
1004 } |
992 } |
1005 } |
993 // Borrow of `self` ends here since we collect cloned paths |
1006 // Borrow of `self` ends here since we collect cloned paths |
994 |
1007 |
995 self.clear_known_ambiguous_mtimes(&paths)?; |
1008 map.clear_known_ambiguous_mtimes(&paths)?; |
996 |
1009 |
997 on_disk::write(self, can_append) |
1010 on_disk::write(map, can_append) |
998 } |
1011 } |
999 |
1012 |
1000 fn status<'a>( |
1013 pub fn status<'a>( |
1001 &'a mut self, |
1014 &'a mut self, |
1002 matcher: &'a (dyn Matcher + Sync), |
1015 matcher: &'a (dyn Matcher + Sync), |
1003 root_dir: PathBuf, |
1016 root_dir: PathBuf, |
1004 ignore_files: Vec<PathBuf>, |
1017 ignore_files: Vec<PathBuf>, |
1005 options: StatusOptions, |
1018 options: StatusOptions, |
1006 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError> |
1019 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError> |
1007 { |
1020 { |
1008 super::status::status(self, matcher, root_dir, ignore_files, options) |
1021 let map = self.get_map_mut(); |
1009 } |
1022 super::status::status(map, matcher, root_dir, ignore_files, options) |
1010 |
1023 } |
1011 fn copy_map_len(&self) -> usize { |
1024 |
1012 self.nodes_with_copy_source_count as usize |
1025 pub fn copy_map_len(&self) -> usize { |
1013 } |
1026 let map = self.get_map(); |
1014 |
1027 map.nodes_with_copy_source_count as usize |
1015 fn copy_map_iter(&self) -> CopyMapIter<'_> { |
1028 } |
1016 Box::new(filter_map_results(self.iter_nodes(), move |node| { |
1029 |
1017 Ok(if let Some(source) = node.copy_source(self.on_disk)? { |
1030 pub fn copy_map_iter(&self) -> CopyMapIter<'_> { |
1018 Some((node.full_path(self.on_disk)?, source)) |
1031 let map = self.get_map(); |
|
1032 Box::new(filter_map_results(map.iter_nodes(), move |node| { |
|
1033 Ok(if let Some(source) = node.copy_source(map.on_disk)? { |
|
1034 Some((node.full_path(map.on_disk)?, source)) |
1019 } else { |
1035 } else { |
1020 None |
1036 None |
1021 }) |
1037 }) |
1022 })) |
1038 })) |
1023 } |
1039 } |
1024 |
1040 |
1025 fn copy_map_contains_key( |
1041 pub fn copy_map_contains_key( |
1026 &self, |
1042 &self, |
1027 key: &HgPath, |
1043 key: &HgPath, |
1028 ) -> Result<bool, DirstateV2ParseError> { |
1044 ) -> Result<bool, DirstateV2ParseError> { |
1029 Ok(if let Some(node) = self.get_node(key)? { |
1045 let map = self.get_map(); |
|
1046 Ok(if let Some(node) = map.get_node(key)? { |
1030 node.has_copy_source() |
1047 node.has_copy_source() |
1031 } else { |
1048 } else { |
1032 false |
1049 false |
1033 }) |
1050 }) |
1034 } |
1051 } |
1035 |
1052 |
1036 fn copy_map_get( |
1053 pub fn copy_map_get( |
1037 &self, |
1054 &self, |
1038 key: &HgPath, |
1055 key: &HgPath, |
1039 ) -> Result<Option<&HgPath>, DirstateV2ParseError> { |
1056 ) -> Result<Option<&HgPath>, DirstateV2ParseError> { |
1040 if let Some(node) = self.get_node(key)? { |
1057 let map = self.get_map(); |
1041 if let Some(source) = node.copy_source(self.on_disk)? { |
1058 if let Some(node) = map.get_node(key)? { |
|
1059 if let Some(source) = node.copy_source(map.on_disk)? { |
1042 return Ok(Some(source)); |
1060 return Ok(Some(source)); |
1043 } |
1061 } |
1044 } |
1062 } |
1045 Ok(None) |
1063 Ok(None) |
1046 } |
1064 } |
1047 |
1065 |
1048 fn copy_map_remove( |
1066 pub fn copy_map_remove( |
1049 &mut self, |
1067 &mut self, |
1050 key: &HgPath, |
1068 key: &HgPath, |
1051 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1069 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1052 let count = &mut self.nodes_with_copy_source_count; |
1070 let map = self.get_map_mut(); |
1053 let unreachable_bytes = &mut self.unreachable_bytes; |
1071 let count = &mut map.nodes_with_copy_source_count; |
1054 Ok(Self::get_node_mut( |
1072 let unreachable_bytes = &mut map.unreachable_bytes; |
1055 self.on_disk, |
1073 Ok(DirstateMap::get_node_mut( |
|
1074 map.on_disk, |
1056 unreachable_bytes, |
1075 unreachable_bytes, |
1057 &mut self.root, |
1076 &mut map.root, |
1058 key, |
1077 key, |
1059 )? |
1078 )? |
1060 .and_then(|node| { |
1079 .and_then(|node| { |
1061 if let Some(source) = &node.copy_source { |
1080 if let Some(source) = &node.copy_source { |
1062 *count -= 1; |
1081 *count -= 1; |
1063 Self::count_dropped_path(unreachable_bytes, source); |
1082 DirstateMap::count_dropped_path(unreachable_bytes, source); |
1064 } |
1083 } |
1065 node.copy_source.take().map(Cow::into_owned) |
1084 node.copy_source.take().map(Cow::into_owned) |
1066 })) |
1085 })) |
1067 } |
1086 } |
1068 |
1087 |
1069 fn copy_map_insert( |
1088 pub fn copy_map_insert( |
1070 &mut self, |
1089 &mut self, |
1071 key: HgPathBuf, |
1090 key: HgPathBuf, |
1072 value: HgPathBuf, |
1091 value: HgPathBuf, |
1073 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1092 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1074 let node = Self::get_or_insert_node( |
1093 let map = self.get_map_mut(); |
1075 self.on_disk, |
1094 let node = DirstateMap::get_or_insert_node( |
1076 &mut self.unreachable_bytes, |
1095 map.on_disk, |
1077 &mut self.root, |
1096 &mut map.unreachable_bytes, |
|
1097 &mut map.root, |
1078 &key, |
1098 &key, |
1079 WithBasename::to_cow_owned, |
1099 WithBasename::to_cow_owned, |
1080 |_ancestor| {}, |
1100 |_ancestor| {}, |
1081 )?; |
1101 )?; |
1082 if node.copy_source.is_none() { |
1102 if node.copy_source.is_none() { |
1083 self.nodes_with_copy_source_count += 1 |
1103 map.nodes_with_copy_source_count += 1 |
1084 } |
1104 } |
1085 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) |
1105 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) |
1086 } |
1106 } |
1087 |
1107 |
1088 fn len(&self) -> usize { |
1108 pub fn len(&self) -> usize { |
1089 self.nodes_with_entry_count as usize |
1109 let map = self.get_map(); |
1090 } |
1110 map.nodes_with_entry_count as usize |
1091 |
1111 } |
1092 fn contains_key( |
1112 |
|
1113 pub fn contains_key( |
1093 &self, |
1114 &self, |
1094 key: &HgPath, |
1115 key: &HgPath, |
1095 ) -> Result<bool, DirstateV2ParseError> { |
1116 ) -> Result<bool, DirstateV2ParseError> { |
1096 Ok(self.get(key)?.is_some()) |
1117 Ok(self.get(key)?.is_some()) |
1097 } |
1118 } |
1098 |
1119 |
1099 fn get( |
1120 pub fn get( |
1100 &self, |
1121 &self, |
1101 key: &HgPath, |
1122 key: &HgPath, |
1102 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { |
1123 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { |
1103 Ok(if let Some(node) = self.get_node(key)? { |
1124 let map = self.get_map(); |
|
1125 Ok(if let Some(node) = map.get_node(key)? { |
1104 node.entry()? |
1126 node.entry()? |
1105 } else { |
1127 } else { |
1106 None |
1128 None |
1107 }) |
1129 }) |
1108 } |
1130 } |
1109 |
1131 |
1110 fn iter(&self) -> StateMapIter<'_> { |
1132 pub fn iter(&self) -> StateMapIter<'_> { |
1111 Box::new(filter_map_results(self.iter_nodes(), move |node| { |
1133 let map = self.get_map(); |
|
1134 Box::new(filter_map_results(map.iter_nodes(), move |node| { |
1112 Ok(if let Some(entry) = node.entry()? { |
1135 Ok(if let Some(entry) = node.entry()? { |
1113 Some((node.full_path(self.on_disk)?, entry)) |
1136 Some((node.full_path(map.on_disk)?, entry)) |
1114 } else { |
1137 } else { |
1115 None |
1138 None |
1116 }) |
1139 }) |
1117 })) |
1140 })) |
1118 } |
1141 } |
1119 |
1142 |
1120 fn iter_tracked_dirs( |
1143 pub fn iter_tracked_dirs( |
1121 &mut self, |
1144 &mut self, |
1122 ) -> Result< |
1145 ) -> Result< |
1123 Box< |
1146 Box< |
1124 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> |
1147 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> |
1125 + Send |
1148 + Send |
1126 + '_, |
1149 + '_, |
1127 >, |
1150 >, |
1128 DirstateError, |
1151 DirstateError, |
1129 > { |
1152 > { |
1130 let on_disk = self.on_disk; |
1153 let map = self.get_map_mut(); |
|
1154 let on_disk = map.on_disk; |
1131 Ok(Box::new(filter_map_results( |
1155 Ok(Box::new(filter_map_results( |
1132 self.iter_nodes(), |
1156 map.iter_nodes(), |
1133 move |node| { |
1157 move |node| { |
1134 Ok(if node.tracked_descendants_count() > 0 { |
1158 Ok(if node.tracked_descendants_count() > 0 { |
1135 Some(node.full_path(on_disk)?) |
1159 Some(node.full_path(on_disk)?) |
1136 } else { |
1160 } else { |
1137 None |
1161 None |
1138 }) |
1162 }) |
1139 }, |
1163 }, |
1140 ))) |
1164 ))) |
1141 } |
1165 } |
1142 |
1166 |
1143 fn debug_iter( |
1167 pub fn debug_iter( |
1144 &self, |
1168 &self, |
1145 all: bool, |
1169 all: bool, |
1146 ) -> Box< |
1170 ) -> Box< |
1147 dyn Iterator< |
1171 dyn Iterator< |
1148 Item = Result< |
1172 Item = Result< |