rust/hg-core/src/dirstate_tree/dirstate_map.rs
changeset 49005 12adf8c695ed
parent 48950 11c0411bf4e2
parent 49003 ce919b1a1063
child 49045 a85c123c625a
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 {