rust/hg-core/src/dirstate_tree/dirstate_map.rs
branchstable
changeset 49000 dd6b67d5c256
parent 48454 473af5cbc209
child 49001 2593873cda0f
equal deleted inserted replaced
48999:cfd270d83169 49000:dd6b67d5c256
   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
  1113                 + Send
  1135                 + Send
  1114                 + '_,
  1136                 + '_,
  1115         >,
  1137         >,
  1116         DirstateError,
  1138         DirstateError,
  1117     > {
  1139     > {
  1118         let map = self.get_map_mut();
  1140         let map = self.get_map();
  1119         let on_disk = map.on_disk;
  1141         let on_disk = map.on_disk;
  1120         Ok(Box::new(filter_map_results(
  1142         Ok(Box::new(filter_map_results(
  1121             map.iter_nodes(),
  1143             map.iter_nodes(),
  1122             move |node| {
  1144             move |node| {
  1123                 Ok(if node.tracked_descendants_count() > 0 {
  1145                 Ok(if node.tracked_descendants_count() > 0 {