##// END OF EJS Templates
dirstate-v2: Make the dirstate bytes buffer available in more places...
Simon Sapin -
r48127:8d0260d0 default
parent child Browse files
Show More
@@ -81,6 +81,7 b" impl<'on_disk> ChildNodes<'on_disk> {"
81 81
82 82 pub(super) fn make_mut(
83 83 &mut self,
84 _on_disk: &'on_disk [u8],
84 85 ) -> Result<
85 86 &mut FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>,
86 87 DirstateV2ParseError,
@@ -95,6 +96,7 b" impl<'tree, 'on_disk> ChildNodesRef<'tre"
95 96 pub(super) fn get(
96 97 &self,
97 98 base_name: &HgPath,
99 _on_disk: &'on_disk [u8],
98 100 ) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
99 101 match self {
100 102 ChildNodesRef::InMemory(nodes) => Ok(nodes
@@ -151,6 +153,7 b" impl<'tree, 'on_disk> ChildNodesRef<'tre"
151 153 impl<'tree, 'on_disk> NodeRef<'tree, 'on_disk> {
152 154 pub(super) fn full_path(
153 155 &self,
156 _on_disk: &'on_disk [u8],
154 157 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
155 158 match self {
156 159 NodeRef::InMemory(path, _node) => Ok(path.full_path()),
@@ -160,6 +163,7 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on"
160 163 /// Returns a `Cow` that can borrow 'on_disk but is detached from 'tree
161 164 pub(super) fn full_path_cow(
162 165 &self,
166 _on_disk: &'on_disk [u8],
163 167 ) -> Result<Cow<'on_disk, HgPath>, DirstateV2ParseError> {
164 168 match self {
165 169 NodeRef::InMemory(path, _node) => Ok(path.full_path().clone()),
@@ -168,6 +172,7 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on"
168 172
169 173 pub(super) fn base_name(
170 174 &self,
175 _on_disk: &'on_disk [u8],
171 176 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
172 177 match self {
173 178 NodeRef::InMemory(path, _node) => Ok(path.base_name()),
@@ -176,6 +181,7 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on"
176 181
177 182 pub(super) fn children(
178 183 &self,
184 _on_disk: &'on_disk [u8],
179 185 ) -> Result<ChildNodesRef<'tree, 'on_disk>, DirstateV2ParseError> {
180 186 match self {
181 187 NodeRef::InMemory(_path, node) => Ok(node.children.as_ref()),
@@ -190,6 +196,7 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on"
190 196
191 197 pub(super) fn copy_source(
192 198 &self,
199 _on_disk: &'on_disk [u8],
193 200 ) -> Result<Option<&'tree HgPath>, DirstateV2ParseError> {
194 201 match self {
195 202 NodeRef::InMemory(_path, node) => {
@@ -274,6 +281,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
274 281 |path, entry, copy_source| {
275 282 let tracked = entry.state.is_tracked();
276 283 let node = Self::get_or_insert_node(
284 map.on_disk,
277 285 &mut map.root,
278 286 path,
279 287 WithBasename::to_cow_borrowed,
@@ -314,10 +322,10 b" impl<'on_disk> DirstateMap<'on_disk> {"
314 322 let mut component =
315 323 components.next().expect("expected at least one components");
316 324 loop {
317 if let Some(child) = children.get(component)? {
325 if let Some(child) = children.get(component, self.on_disk)? {
318 326 if let Some(next_component) = components.next() {
319 327 component = next_component;
320 children = child.children()?;
328 children = child.children(self.on_disk)?;
321 329 } else {
322 330 return Ok(Some(child));
323 331 }
@@ -332,6 +340,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
332 340 /// This takes `root` instead of `&mut self` so that callers can mutate
333 341 /// other fields while the returned borrow is still valid
334 342 fn get_node_mut<'tree>(
343 on_disk: &'on_disk [u8],
335 344 root: &'tree mut ChildNodes<'on_disk>,
336 345 path: &HgPath,
337 346 ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> {
@@ -340,7 +349,8 b" impl<'on_disk> DirstateMap<'on_disk> {"
340 349 let mut component =
341 350 components.next().expect("expected at least one components");
342 351 loop {
343 if let Some(child) = children.make_mut()?.get_mut(component) {
352 if let Some(child) = children.make_mut(on_disk)?.get_mut(component)
353 {
344 354 if let Some(next_component) = components.next() {
345 355 component = next_component;
346 356 children = &mut child.children;
@@ -354,6 +364,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
354 364 }
355 365
356 366 fn get_or_insert_node<'tree, 'path>(
367 on_disk: &'on_disk [u8],
357 368 root: &'tree mut ChildNodes<'on_disk>,
358 369 path: &'path HgPath,
359 370 to_cow: impl Fn(
@@ -372,7 +383,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
372 383 // map already contains that key, without introducing double
373 384 // lookup?
374 385 let child_node = child_nodes
375 .make_mut()?
386 .make_mut(on_disk)?
376 387 .entry(to_cow(ancestor_path))
377 388 .or_default();
378 389 if let Some(next) = inclusive_ancestor_paths.next() {
@@ -399,6 +410,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
399 410 };
400 411
401 412 let node = Self::get_or_insert_node(
413 self.on_disk,
402 414 &mut self.root,
403 415 path,
404 416 WithBasename::to_cow_owned,
@@ -448,7 +460,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
448 460 let mut iter = self.root.as_ref().iter();
449 461 std::iter::from_fn(move || {
450 462 while let Some(child_node) = iter.next() {
451 let children = match child_node.children() {
463 let children = match child_node.children(self.on_disk) {
452 464 Ok(children) => children,
453 465 Err(error) => return Some(Err(error)),
454 466 };
@@ -476,9 +488,11 b" impl<'on_disk> DirstateMap<'on_disk> {"
476 488 paths: &[impl AsRef<HgPath>],
477 489 ) -> Result<(), DirstateV2ParseError> {
478 490 for path in paths {
479 if let Some(node) =
480 Self::get_node_mut(&mut self.root, path.as_ref())?
481 {
491 if let Some(node) = Self::get_node_mut(
492 self.on_disk,
493 &mut self.root,
494 path.as_ref(),
495 )? {
482 496 if let Some(entry) = node.entry.as_mut() {
483 497 entry.clear_mtime();
484 498 }
@@ -501,7 +515,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
501 515 filter_map_results(self.iter_nodes(), move |node| {
502 516 if let Some(entry) = node.entry()? {
503 517 if predicate(&entry) {
504 return Ok(Some(node.full_path()?));
518 return Ok(Some(node.full_path(self.on_disk)?));
505 519 }
506 520 }
507 521 Ok(None)
@@ -570,14 +584,15 b" impl<'on_disk> super::dispatch::Dirstate"
570 584 had_entry: bool,
571 585 had_copy_source: bool,
572 586 }
573 fn recur(
574 nodes: &mut ChildNodes,
587 fn recur<'on_disk>(
588 on_disk: &'on_disk [u8],
589 nodes: &mut ChildNodes<'on_disk>,
575 590 path: &HgPath,
576 591 ) -> Result<Option<Dropped>, DirstateV2ParseError> {
577 592 let (first_path_component, rest_of_path) =
578 593 path.split_first_component();
579 594 let node = if let Some(node) =
580 nodes.make_mut()?.get_mut(first_path_component)
595 nodes.make_mut(on_disk)?.get_mut(first_path_component)
581 596 {
582 597 node
583 598 } else {
@@ -585,7 +600,7 b" impl<'on_disk> super::dispatch::Dirstate"
585 600 };
586 601 let dropped;
587 602 if let Some(rest) = rest_of_path {
588 if let Some(d) = recur(&mut node.children, rest)? {
603 if let Some(d) = recur(on_disk, &mut node.children, rest)? {
589 604 dropped = d;
590 605 if dropped.was_tracked {
591 606 node.tracked_descendants_count -= 1;
@@ -609,12 +624,12 b" impl<'on_disk> super::dispatch::Dirstate"
609 624 && node.copy_source.is_none()
610 625 && node.children.is_empty()
611 626 {
612 nodes.make_mut()?.remove(first_path_component);
627 nodes.make_mut(on_disk)?.remove(first_path_component);
613 628 }
614 629 Ok(Some(dropped))
615 630 }
616 631
617 if let Some(dropped) = recur(&mut self.root, filename)? {
632 if let Some(dropped) = recur(self.on_disk, &mut self.root, filename)? {
618 633 if dropped.had_entry {
619 634 self.nodes_with_entry_count -= 1
620 635 }
@@ -634,7 +649,8 b" impl<'on_disk> super::dispatch::Dirstate"
634 649 now: i32,
635 650 ) -> Result<(), DirstateV2ParseError> {
636 651 for filename in filenames {
637 if let Some(node) = Self::get_node_mut(&mut self.root, &filename)?
652 if let Some(node) =
653 Self::get_node_mut(self.on_disk, &mut self.root, &filename)?
638 654 {
639 655 if let Some(entry) = node.entry.as_mut() {
640 656 entry.clear_ambiguous_mtime(now);
@@ -735,10 +751,12 b" impl<'on_disk> super::dispatch::Dirstate"
735 751 for node in self.iter_nodes() {
736 752 let node = node?;
737 753 if let Some(entry) = node.entry()? {
738 size +=
739 packed_entry_size(node.full_path()?, node.copy_source()?);
754 size += packed_entry_size(
755 node.full_path(self.on_disk)?,
756 node.copy_source(self.on_disk)?,
757 );
740 758 if entry.mtime_is_ambiguous(now) {
741 ambiguous_mtimes.push(node.full_path_cow()?)
759 ambiguous_mtimes.push(node.full_path_cow(self.on_disk)?)
742 760 }
743 761 }
744 762 }
@@ -751,9 +769,9 b" impl<'on_disk> super::dispatch::Dirstate"
751 769 let node = node?;
752 770 if let Some(entry) = node.entry()? {
753 771 pack_entry(
754 node.full_path()?,
772 node.full_path(self.on_disk)?,
755 773 &entry,
756 node.copy_source()?,
774 node.copy_source(self.on_disk)?,
757 775 &mut packed,
758 776 );
759 777 }
@@ -774,7 +792,7 b" impl<'on_disk> super::dispatch::Dirstate"
774 792 let node = node?;
775 793 if let Some(entry) = node.entry()? {
776 794 if entry.mtime_is_ambiguous(now) {
777 paths.push(node.full_path_cow()?)
795 paths.push(node.full_path_cow(self.on_disk)?)
778 796 }
779 797 }
780 798 }
@@ -813,9 +831,9 b" impl<'on_disk> super::dispatch::Dirstate"
813 831 }
814 832
815 833 fn copy_map_iter(&self) -> CopyMapIter<'_> {
816 Box::new(filter_map_results(self.iter_nodes(), |node| {
817 Ok(if let Some(source) = node.copy_source()? {
818 Some((node.full_path()?, source))
834 Box::new(filter_map_results(self.iter_nodes(), move |node| {
835 Ok(if let Some(source) = node.copy_source(self.on_disk)? {
836 Some((node.full_path(self.on_disk)?, source))
819 837 } else {
820 838 None
821 839 })
@@ -838,7 +856,7 b" impl<'on_disk> super::dispatch::Dirstate"
838 856 key: &HgPath,
839 857 ) -> Result<Option<&HgPath>, DirstateV2ParseError> {
840 858 if let Some(node) = self.get_node(key)? {
841 if let Some(source) = node.copy_source()? {
859 if let Some(source) = node.copy_source(self.on_disk)? {
842 860 return Ok(Some(source));
843 861 }
844 862 }
@@ -850,12 +868,16 b" impl<'on_disk> super::dispatch::Dirstate"
850 868 key: &HgPath,
851 869 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
852 870 let count = &mut self.nodes_with_copy_source_count;
853 Ok(Self::get_node_mut(&mut self.root, key)?.and_then(|node| {
854 if node.copy_source.is_some() {
855 *count -= 1
856 }
857 node.copy_source.take().map(Cow::into_owned)
858 }))
871 Ok(
872 Self::get_node_mut(self.on_disk, &mut self.root, key)?.and_then(
873 |node| {
874 if node.copy_source.is_some() {
875 *count -= 1
876 }
877 node.copy_source.take().map(Cow::into_owned)
878 },
879 ),
880 )
859 881 }
860 882
861 883 fn copy_map_insert(
@@ -864,6 +886,7 b" impl<'on_disk> super::dispatch::Dirstate"
864 886 value: HgPathBuf,
865 887 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
866 888 let node = Self::get_or_insert_node(
889 self.on_disk,
867 890 &mut self.root,
868 891 &key,
869 892 WithBasename::to_cow_owned,
@@ -898,9 +921,9 b" impl<'on_disk> super::dispatch::Dirstate"
898 921 }
899 922
900 923 fn iter(&self) -> StateMapIter<'_> {
901 Box::new(filter_map_results(self.iter_nodes(), |node| {
924 Box::new(filter_map_results(self.iter_nodes(), move |node| {
902 925 Ok(if let Some(entry) = node.entry()? {
903 Some((node.full_path()?, entry))
926 Some((node.full_path(self.on_disk)?, entry))
904 927 } else {
905 928 None
906 929 })
@@ -272,7 +272,8 b' pub(super) fn write('
272 272 // actual offset for the root nodes.
273 273 out.resize(header_len, 0_u8);
274 274
275 let root = write_nodes(dirstate_map.root.as_ref(), &mut out)?;
275 let root =
276 write_nodes(dirstate_map, dirstate_map.root.as_ref(), &mut out)?;
276 277
277 278 let header = Header {
278 279 marker: *V2_FORMAT_MARKER,
@@ -288,6 +289,7 b' pub(super) fn write('
288 289 }
289 290
290 291 fn write_nodes(
292 dirstate_map: &DirstateMap,
291 293 nodes: dirstate_map::ChildNodesRef,
292 294 out: &mut Vec<u8>,
293 295 ) -> Result<ChildNodes, DirstateError> {
@@ -298,16 +300,19 b' fn write_nodes('
298 300 // First accumulate serialized nodes in a `Vec`
299 301 let mut on_disk_nodes = Vec::with_capacity(nodes.len());
300 302 for node in nodes {
301 let children = write_nodes(node.children()?, out)?;
302 let full_path = write_slice::<u8>(node.full_path()?.as_bytes(), out);
303 let copy_source = if let Some(source) = node.copy_source()? {
304 write_slice::<u8>(source.as_bytes(), out)
305 } else {
306 Slice {
307 start: 0.into(),
308 len: 0.into(),
309 }
310 };
303 let children = node.children(dirstate_map.on_disk)?;
304 let children = write_nodes(dirstate_map, children, out)?;
305 let full_path = node.full_path(dirstate_map.on_disk)?;
306 let full_path = write_slice::<u8>(full_path.as_bytes(), out);
307 let copy_source =
308 if let Some(source) = node.copy_source(dirstate_map.on_disk)? {
309 write_slice::<u8>(source.as_bytes(), out)
310 } else {
311 Slice {
312 start: 0.into(),
313 len: 0.into(),
314 }
315 };
311 316 on_disk_nodes.push(match node {
312 317 NodeRef::InMemory(path, node) => Node {
313 318 children,
@@ -32,8 +32,8 b' use std::sync::Mutex;'
32 32 /// exists in one of the two trees, depending on information requested by
33 33 /// `options` we may need to traverse the remaining subtree.
34 34 #[timed]
35 pub fn status<'tree>(
36 dmap: &'tree mut DirstateMap,
35 pub fn status<'tree, 'on_disk: 'tree>(
36 dmap: &'tree mut DirstateMap<'on_disk>,
37 37 matcher: &(dyn Matcher + Sync),
38 38 root_dir: PathBuf,
39 39 ignore_files: Vec<PathBuf>,
@@ -47,6 +47,7 b" pub fn status<'tree>("
47 47 };
48 48
49 49 let common = StatusCommon {
50 dmap,
50 51 options,
51 52 matcher,
52 53 ignore_fn,
@@ -67,14 +68,15 b" pub fn status<'tree>("
67 68
68 69 /// Bag of random things needed by various parts of the algorithm. Reduces the
69 70 /// number of parameters passed to functions.
70 struct StatusCommon<'tree, 'a> {
71 struct StatusCommon<'tree, 'a, 'on_disk: 'tree> {
72 dmap: &'tree DirstateMap<'on_disk>,
71 73 options: StatusOptions,
72 74 matcher: &'a (dyn Matcher + Sync),
73 75 ignore_fn: IgnoreFnType<'a>,
74 76 outcome: Mutex<DirstateStatus<'tree>>,
75 77 }
76 78
77 impl<'tree, 'a> StatusCommon<'tree, 'a> {
79 impl<'tree, 'a> StatusCommon<'tree, 'a, '_> {
78 80 fn read_dir(
79 81 &self,
80 82 hg_path: &HgPath,
@@ -119,7 +121,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
119 121 // Propagate here any error that would happen inside the comparison
120 122 // callback below
121 123 for dirstate_node in &dirstate_nodes {
122 dirstate_node.base_name()?;
124 dirstate_node.base_name(self.dmap.on_disk)?;
123 125 }
124 126 itertools::merge_join_by(
125 127 dirstate_nodes,
@@ -127,7 +129,10 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
127 129 |dirstate_node, fs_entry| {
128 130 // This `unwrap` never panics because we already propagated
129 131 // those errors above
130 dirstate_node.base_name().unwrap().cmp(&fs_entry.base_name)
132 dirstate_node
133 .base_name(self.dmap.on_disk)
134 .unwrap()
135 .cmp(&fs_entry.base_name)
131 136 },
132 137 )
133 138 .par_bridge()
@@ -159,7 +164,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
159 164 dirstate_node: NodeRef<'tree, '_>,
160 165 has_ignored_ancestor: bool,
161 166 ) -> Result<(), DirstateV2ParseError> {
162 let hg_path = dirstate_node.full_path()?;
167 let hg_path = dirstate_node.full_path(self.dmap.on_disk)?;
163 168 let file_type = fs_entry.metadata.file_type();
164 169 let file_or_symlink = file_type.is_file() || file_type.is_symlink();
165 170 if !file_or_symlink {
@@ -179,7 +184,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
179 184 let is_at_repo_root = false;
180 185 self.traverse_fs_directory_and_dirstate(
181 186 is_ignored,
182 dirstate_node.children()?,
187 dirstate_node.children(self.dmap.on_disk)?,
183 188 hg_path,
184 189 &fs_entry.full_path,
185 190 is_at_repo_root,
@@ -221,7 +226,8 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
221 226 }
222 227 }
223 228
224 for child_node in dirstate_node.children()?.iter() {
229 for child_node in dirstate_node.children(self.dmap.on_disk)?.iter()
230 {
225 231 self.traverse_dirstate_only(child_node)?
226 232 }
227 233 }
@@ -246,7 +252,7 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
246 252 let entry = dirstate_node
247 253 .entry()?
248 254 .expect("handle_normal_file called with entry-less node");
249 let full_path = Cow::from(dirstate_node.full_path()?);
255 let full_path = Cow::from(dirstate_node.full_path(self.dmap.on_disk)?);
250 256 let mode_changed = || {
251 257 self.options.check_exec && entry.mode_changed(&fs_entry.metadata)
252 258 };
@@ -282,11 +288,11 b" impl<'tree, 'a> StatusCommon<'tree, 'a> "
282 288 dirstate_node: NodeRef<'tree, '_>,
283 289 ) -> Result<(), DirstateV2ParseError> {
284 290 self.mark_removed_or_deleted_if_file(
285 dirstate_node.full_path()?,
291 dirstate_node.full_path(self.dmap.on_disk)?,
286 292 dirstate_node.state()?,
287 293 );
288 294 dirstate_node
289 .children()?
295 .children(self.dmap.on_disk)?
290 296 .par_iter()
291 297 .map(|child_node| self.traverse_dirstate_only(child_node))
292 298 .collect()
General Comments 0
You need to be logged in to leave comments. Login now