723 }) |
723 }) |
724 } |
724 } |
725 |
725 |
726 impl OwningDirstateMap { |
726 impl OwningDirstateMap { |
727 pub fn clear(&mut self) { |
727 pub fn clear(&mut self) { |
728 let map = self.get_map_mut(); |
728 self.with_dmap_mut(|map| { |
729 map.root = Default::default(); |
729 map.root = Default::default(); |
730 map.nodes_with_entry_count = 0; |
730 map.nodes_with_entry_count = 0; |
731 map.nodes_with_copy_source_count = 0; |
731 map.nodes_with_copy_source_count = 0; |
|
732 }); |
732 } |
733 } |
733 |
734 |
734 pub fn set_entry( |
735 pub fn set_entry( |
735 &mut self, |
736 &mut self, |
736 filename: &HgPath, |
737 filename: &HgPath, |
737 entry: DirstateEntry, |
738 entry: DirstateEntry, |
738 ) -> Result<(), DirstateV2ParseError> { |
739 ) -> Result<(), DirstateV2ParseError> { |
739 let map = self.get_map_mut(); |
740 self.with_dmap_mut(|map| { |
740 map.get_or_insert(&filename)?.data = NodeData::Entry(entry); |
741 map.get_or_insert(&filename)?.data = NodeData::Entry(entry); |
741 Ok(()) |
742 Ok(()) |
|
743 }) |
742 } |
744 } |
743 |
745 |
744 pub fn add_file( |
746 pub fn add_file( |
745 &mut self, |
747 &mut self, |
746 filename: &HgPath, |
748 filename: &HgPath, |
747 entry: DirstateEntry, |
749 entry: DirstateEntry, |
748 ) -> Result<(), DirstateError> { |
750 ) -> Result<(), DirstateError> { |
749 let old_state = self.get(filename)?.map(|e| e.state()); |
751 let old_state = self.get(filename)?.map(|e| e.state()); |
750 let map = self.get_map_mut(); |
752 self.with_dmap_mut(|map| { |
751 Ok(map.add_or_remove_file(filename, old_state, entry)?) |
753 Ok(map.add_or_remove_file(filename, old_state, entry)?) |
|
754 }) |
752 } |
755 } |
753 |
756 |
754 pub fn remove_file( |
757 pub fn remove_file( |
755 &mut self, |
758 &mut self, |
756 filename: &HgPath, |
759 filename: &HgPath, |
777 } |
780 } |
778 } |
781 } |
779 if size == 0 { |
782 if size == 0 { |
780 self.copy_map_remove(filename)?; |
783 self.copy_map_remove(filename)?; |
781 } |
784 } |
782 let map = self.get_map_mut(); |
785 self.with_dmap_mut(|map| { |
783 let entry = DirstateEntry::new_removed(size); |
786 let entry = DirstateEntry::new_removed(size); |
784 Ok(map.add_or_remove_file(filename, old_state, entry)?) |
787 Ok(map.add_or_remove_file(filename, old_state, entry)?) |
|
788 }) |
785 } |
789 } |
786 |
790 |
787 pub fn drop_entry_and_copy_source( |
791 pub fn drop_entry_and_copy_source( |
788 &mut self, |
792 &mut self, |
789 filename: &HgPath, |
793 filename: &HgPath, |
790 ) -> Result<(), DirstateError> { |
794 ) -> Result<(), DirstateError> { |
791 let was_tracked = self |
795 let was_tracked = self |
792 .get(filename)? |
796 .get(filename)? |
793 .map_or(false, |e| e.state().is_tracked()); |
797 .map_or(false, |e| e.state().is_tracked()); |
794 let map = self.get_map_mut(); |
|
795 struct Dropped { |
798 struct Dropped { |
796 was_tracked: bool, |
799 was_tracked: bool, |
797 had_entry: bool, |
800 had_entry: bool, |
798 had_copy_source: bool, |
801 had_copy_source: bool, |
799 } |
802 } |
876 ) |
879 ) |
877 } |
880 } |
878 Ok(Some((dropped, remove))) |
881 Ok(Some((dropped, remove))) |
879 } |
882 } |
880 |
883 |
881 if let Some((dropped, _removed)) = recur( |
884 self.with_dmap_mut(|map| { |
882 map.on_disk, |
885 if let Some((dropped, _removed)) = recur( |
883 &mut map.unreachable_bytes, |
886 map.on_disk, |
884 &mut map.root, |
887 &mut map.unreachable_bytes, |
885 filename, |
888 &mut map.root, |
886 )? { |
889 filename, |
887 if dropped.had_entry { |
890 )? { |
888 map.nodes_with_entry_count -= 1 |
891 if dropped.had_entry { |
889 } |
892 map.nodes_with_entry_count -= 1 |
890 if dropped.had_copy_source { |
893 } |
891 map.nodes_with_copy_source_count -= 1 |
894 if dropped.had_copy_source { |
892 } |
895 map.nodes_with_copy_source_count -= 1 |
893 } else { |
896 } |
894 debug_assert!(!was_tracked); |
897 } else { |
895 } |
898 debug_assert!(!was_tracked); |
896 Ok(()) |
899 } |
|
900 Ok(()) |
|
901 }) |
897 } |
902 } |
898 |
903 |
899 pub fn has_tracked_dir( |
904 pub fn has_tracked_dir( |
900 &mut self, |
905 &mut self, |
901 directory: &HgPath, |
906 directory: &HgPath, |
902 ) -> Result<bool, DirstateError> { |
907 ) -> Result<bool, DirstateError> { |
903 let map = self.get_map_mut(); |
908 self.with_dmap_mut(|map| { |
904 if let Some(node) = map.get_node(directory)? { |
909 if let Some(node) = map.get_node(directory)? { |
905 // A node without a `DirstateEntry` was created to hold child |
910 // A node without a `DirstateEntry` was created to hold child |
906 // nodes, and is therefore a directory. |
911 // nodes, and is therefore a directory. |
907 let state = node.state()?; |
912 let state = node.state()?; |
908 Ok(state.is_none() && node.tracked_descendants_count() > 0) |
913 Ok(state.is_none() && node.tracked_descendants_count() > 0) |
909 } else { |
914 } else { |
910 Ok(false) |
915 Ok(false) |
911 } |
916 } |
|
917 }) |
912 } |
918 } |
913 |
919 |
914 pub fn has_dir( |
920 pub fn has_dir( |
915 &mut self, |
921 &mut self, |
916 directory: &HgPath, |
922 directory: &HgPath, |
917 ) -> Result<bool, DirstateError> { |
923 ) -> Result<bool, DirstateError> { |
918 let map = self.get_map_mut(); |
924 self.with_dmap_mut(|map| { |
919 if let Some(node) = map.get_node(directory)? { |
925 if let Some(node) = map.get_node(directory)? { |
920 // A node without a `DirstateEntry` was created to hold child |
926 // A node without a `DirstateEntry` was created to hold child |
921 // nodes, and is therefore a directory. |
927 // nodes, and is therefore a directory. |
922 let state = node.state()?; |
928 let state = node.state()?; |
923 Ok(state.is_none() && node.descendants_with_entry_count() > 0) |
929 Ok(state.is_none() && node.descendants_with_entry_count() > 0) |
924 } else { |
930 } else { |
925 Ok(false) |
931 Ok(false) |
926 } |
932 } |
|
933 }) |
927 } |
934 } |
928 |
935 |
929 #[timed] |
936 #[timed] |
930 pub fn pack_v1( |
937 pub fn pack_v1( |
931 &self, |
938 &self, |
973 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> { |
980 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> { |
974 let map = self.get_map(); |
981 let map = self.get_map(); |
975 on_disk::write(map, can_append) |
982 on_disk::write(map, can_append) |
976 } |
983 } |
977 |
984 |
978 pub fn status<'a>( |
985 /// `callback` allows the caller to process and do something with the |
979 &'a mut self, |
986 /// results of the status. This is needed to do so efficiently (i.e. |
980 matcher: &'a (dyn Matcher + Sync), |
987 /// without cloning the `DirstateStatus` object with its paths) because |
|
988 /// we need to borrow from `Self`. |
|
989 pub fn with_status<R>( |
|
990 &mut self, |
|
991 matcher: &(dyn Matcher + Sync), |
981 root_dir: PathBuf, |
992 root_dir: PathBuf, |
982 ignore_files: Vec<PathBuf>, |
993 ignore_files: Vec<PathBuf>, |
983 options: StatusOptions, |
994 options: StatusOptions, |
984 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError> |
995 callback: impl for<'r> FnOnce( |
985 { |
996 Result<(DirstateStatus<'r>, Vec<PatternFileWarning>), StatusError>, |
986 let map = self.get_map_mut(); |
997 ) -> R, |
987 super::status::status(map, matcher, root_dir, ignore_files, options) |
998 ) -> R { |
|
999 self.with_dmap_mut(|map| { |
|
1000 callback(super::status::status( |
|
1001 map, |
|
1002 matcher, |
|
1003 root_dir, |
|
1004 ignore_files, |
|
1005 options, |
|
1006 )) |
|
1007 }) |
988 } |
1008 } |
989 |
1009 |
990 pub fn copy_map_len(&self) -> usize { |
1010 pub fn copy_map_len(&self) -> usize { |
991 let map = self.get_map(); |
1011 let map = self.get_map(); |
992 map.nodes_with_copy_source_count as usize |
1012 map.nodes_with_copy_source_count as usize |
1030 |
1050 |
1031 pub fn copy_map_remove( |
1051 pub fn copy_map_remove( |
1032 &mut self, |
1052 &mut self, |
1033 key: &HgPath, |
1053 key: &HgPath, |
1034 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1054 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1035 let map = self.get_map_mut(); |
1055 self.with_dmap_mut(|map| { |
1036 let count = &mut map.nodes_with_copy_source_count; |
1056 let count = &mut map.nodes_with_copy_source_count; |
1037 let unreachable_bytes = &mut map.unreachable_bytes; |
1057 let unreachable_bytes = &mut map.unreachable_bytes; |
1038 Ok(DirstateMap::get_node_mut( |
1058 Ok(DirstateMap::get_node_mut( |
1039 map.on_disk, |
1059 map.on_disk, |
1040 unreachable_bytes, |
1060 unreachable_bytes, |
1041 &mut map.root, |
1061 &mut map.root, |
1042 key, |
1062 key, |
1043 )? |
1063 )? |
1044 .and_then(|node| { |
1064 .and_then(|node| { |
1045 if let Some(source) = &node.copy_source { |
1065 if let Some(source) = &node.copy_source { |
1046 *count -= 1; |
1066 *count -= 1; |
1047 DirstateMap::count_dropped_path(unreachable_bytes, source); |
1067 DirstateMap::count_dropped_path(unreachable_bytes, source); |
1048 } |
1068 } |
1049 node.copy_source.take().map(Cow::into_owned) |
1069 node.copy_source.take().map(Cow::into_owned) |
1050 })) |
1070 })) |
|
1071 }) |
1051 } |
1072 } |
1052 |
1073 |
1053 pub fn copy_map_insert( |
1074 pub fn copy_map_insert( |
1054 &mut self, |
1075 &mut self, |
1055 key: HgPathBuf, |
1076 key: HgPathBuf, |
1056 value: HgPathBuf, |
1077 value: HgPathBuf, |
1057 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1078 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { |
1058 let map = self.get_map_mut(); |
1079 self.with_dmap_mut(|map| { |
1059 let node = DirstateMap::get_or_insert_node( |
1080 let node = DirstateMap::get_or_insert_node( |
1060 map.on_disk, |
1081 map.on_disk, |
1061 &mut map.unreachable_bytes, |
1082 &mut map.unreachable_bytes, |
1062 &mut map.root, |
1083 &mut map.root, |
1063 &key, |
1084 &key, |
1064 WithBasename::to_cow_owned, |
1085 WithBasename::to_cow_owned, |
1065 |_ancestor| {}, |
1086 |_ancestor| {}, |
1066 )?; |
1087 )?; |
1067 if node.copy_source.is_none() { |
1088 if node.copy_source.is_none() { |
1068 map.nodes_with_copy_source_count += 1 |
1089 map.nodes_with_copy_source_count += 1 |
1069 } |
1090 } |
1070 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) |
1091 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) |
|
1092 }) |
1071 } |
1093 } |
1072 |
1094 |
1073 pub fn len(&self) -> usize { |
1095 pub fn len(&self) -> usize { |
1074 let map = self.get_map(); |
1096 let map = self.get_map(); |
1075 map.nodes_with_entry_count as usize |
1097 map.nodes_with_entry_count as usize |