##// END OF EJS Templates
dirstate-tree: Borrow copy source paths from the "on disk" bytes...
Simon Sapin -
r47895:9be61845 default
parent child Browse files
Show More
@@ -1,5 +1,6 b''
1 use bytes_cast::BytesCast;
1 use bytes_cast::BytesCast;
2 use micro_timer::timed;
2 use micro_timer::timed;
3 use std::borrow::Cow;
3 use std::convert::TryInto;
4 use std::convert::TryInto;
4 use std::path::PathBuf;
5 use std::path::PathBuf;
5
6
@@ -28,7 +29,7 b" pub struct DirstateMap<'on_disk> {"
28 /// Contents of the `.hg/dirstate` file
29 /// Contents of the `.hg/dirstate` file
29 on_disk: &'on_disk [u8],
30 on_disk: &'on_disk [u8],
30
31
31 pub(super) root: ChildNodes,
32 pub(super) root: ChildNodes<'on_disk>,
32
33
33 /// Number of nodes anywhere in the tree that have `.entry.is_some()`.
34 /// Number of nodes anywhere in the tree that have `.entry.is_some()`.
34 nodes_with_entry_count: usize,
35 nodes_with_entry_count: usize,
@@ -43,33 +44,34 b" pub struct DirstateMap<'on_disk> {"
43 /// path, so comparing full paths gives the same result as comparing base
44 /// path, so comparing full paths gives the same result as comparing base
44 /// names. However `BTreeMap` would waste time always re-comparing the same
45 /// names. However `BTreeMap` would waste time always re-comparing the same
45 /// string prefix.
46 /// string prefix.
46 pub(super) type ChildNodes = FastHashMap<WithBasename<HgPathBuf>, Node>;
47 pub(super) type ChildNodes<'on_disk> =
48 FastHashMap<WithBasename<HgPathBuf>, Node<'on_disk>>;
47
49
48 /// Represents a file or a directory
50 /// Represents a file or a directory
49 #[derive(Default)]
51 #[derive(Default)]
50 pub(super) struct Node {
52 pub(super) struct Node<'on_disk> {
51 /// `None` for directories
53 /// `None` for directories
52 pub(super) entry: Option<DirstateEntry>,
54 pub(super) entry: Option<DirstateEntry>,
53
55
54 pub(super) copy_source: Option<HgPathBuf>,
56 pub(super) copy_source: Option<Cow<'on_disk, HgPath>>,
55
57
56 pub(super) children: ChildNodes,
58 pub(super) children: ChildNodes<'on_disk>,
57
59
58 /// How many (non-inclusive) descendants of this node are tracked files
60 /// How many (non-inclusive) descendants of this node are tracked files
59 tracked_descendants_count: usize,
61 tracked_descendants_count: usize,
60 }
62 }
61
63
62 impl Node {
64 impl Node<'_> {
63 pub(super) fn state(&self) -> Option<EntryState> {
65 pub(super) fn state(&self) -> Option<EntryState> {
64 self.entry.as_ref().map(|entry| entry.state)
66 self.entry.as_ref().map(|entry| entry.state)
65 }
67 }
66 }
68 }
67
69
68 /// `(full_path, entry, copy_source)`
70 /// `(full_path, entry, copy_source)`
69 type NodeDataMut<'a> = (
71 type NodeDataMut<'tree, 'on_disk> = (
70 &'a HgPath,
72 &'tree HgPath,
71 &'a mut Option<DirstateEntry>,
73 &'tree mut Option<DirstateEntry>,
72 &'a mut Option<HgPathBuf>,
74 &'tree mut Option<Cow<'on_disk, HgPath>>,
73 );
75 );
74
76
75 impl<'on_disk> DirstateMap<'on_disk> {
77 impl<'on_disk> DirstateMap<'on_disk> {
@@ -115,7 +117,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
115 "duplicate dirstate entry in read"
117 "duplicate dirstate entry in read"
116 );
118 );
117 node.entry = Some(*entry);
119 node.entry = Some(*entry);
118 node.copy_source = copy_source.map(HgPath::to_owned);
120 node.copy_source = copy_source.map(Cow::Borrowed);
119 self.nodes_with_entry_count += 1;
121 self.nodes_with_entry_count += 1;
120 if copy_source.is_some() {
122 if copy_source.is_some() {
121 self.nodes_with_copy_source_count += 1
123 self.nodes_with_copy_source_count += 1
@@ -147,9 +149,9 b" impl<'on_disk> DirstateMap<'on_disk> {"
147 /// This takes `root` instead of `&mut self` so that callers can mutate
149 /// This takes `root` instead of `&mut self` so that callers can mutate
148 /// other fields while the returned borrow is still valid
150 /// other fields while the returned borrow is still valid
149 fn get_node_mut<'tree>(
151 fn get_node_mut<'tree>(
150 root: &'tree mut ChildNodes,
152 root: &'tree mut ChildNodes<'on_disk>,
151 path: &HgPath,
153 path: &HgPath,
152 ) -> Option<&'tree mut Node> {
154 ) -> Option<&'tree mut Node<'on_disk>> {
153 Self::get_node_mut_tracing_ancestors(root, path, |_| {})
155 Self::get_node_mut_tracing_ancestors(root, path, |_| {})
154 }
156 }
155
157
@@ -159,10 +161,10 b" impl<'on_disk> DirstateMap<'on_disk> {"
159 /// Note that `each_ancestor` may be called (with what would be ancestors)
161 /// Note that `each_ancestor` may be called (with what would be ancestors)
160 /// even if it turns out there is no node at `path`.
162 /// even if it turns out there is no node at `path`.
161 fn get_node_mut_tracing_ancestors<'tree>(
163 fn get_node_mut_tracing_ancestors<'tree>(
162 root: &'tree mut ChildNodes,
164 root: &'tree mut ChildNodes<'on_disk>,
163 path: &HgPath,
165 path: &HgPath,
164 mut each_ancestor: impl FnMut(&mut Node),
166 mut each_ancestor: impl FnMut(&mut Node),
165 ) -> Option<&'tree mut Node> {
167 ) -> Option<&'tree mut Node<'on_disk>> {
166 let mut children = root;
168 let mut children = root;
167 let mut components = path.components();
169 let mut components = path.components();
168 let mut component =
170 let mut component =
@@ -180,17 +182,17 b" impl<'on_disk> DirstateMap<'on_disk> {"
180 }
182 }
181
183
182 fn get_or_insert_node<'tree>(
184 fn get_or_insert_node<'tree>(
183 root: &'tree mut ChildNodes,
185 root: &'tree mut ChildNodes<'on_disk>,
184 path: &HgPath,
186 path: &HgPath,
185 ) -> &'tree mut Node {
187 ) -> &'tree mut Node<'on_disk> {
186 Self::get_or_insert_node_tracing_ancestors(root, path, |_| {})
188 Self::get_or_insert_node_tracing_ancestors(root, path, |_| {})
187 }
189 }
188
190
189 fn get_or_insert_node_tracing_ancestors<'tree>(
191 fn get_or_insert_node_tracing_ancestors<'tree>(
190 root: &'tree mut ChildNodes,
192 root: &'tree mut ChildNodes<'on_disk>,
191 path: &HgPath,
193 path: &HgPath,
192 mut each_ancestor: impl FnMut(&mut Node),
194 mut each_ancestor: impl FnMut(&mut Node),
193 ) -> &'tree mut Node {
195 ) -> &'tree mut Node<'on_disk> {
194 let mut child_nodes = root;
196 let mut child_nodes = root;
195 let mut inclusive_ancestor_paths =
197 let mut inclusive_ancestor_paths =
196 WithBasename::inclusive_ancestors_of(path);
198 WithBasename::inclusive_ancestors_of(path);
@@ -298,9 +300,9 b" impl<'on_disk> DirstateMap<'on_disk> {"
298 /// with `-> impl Iterator<Item = &mut Node>` since child nodes are
300 /// with `-> impl Iterator<Item = &mut Node>` since child nodes are
299 /// reachable from their ancestor nodes, potentially creating multiple
301 /// reachable from their ancestor nodes, potentially creating multiple
300 /// `&mut` references to a given node.
302 /// `&mut` references to a given node.
301 fn iter_node_data_mut<'a>(
303 fn iter_node_data_mut<'tree>(
302 &'a mut self,
304 &'tree mut self,
303 ) -> impl Iterator<Item = NodeDataMut<'a>> + 'a {
305 ) -> impl Iterator<Item = NodeDataMut<'tree, 'on_disk>> + 'tree {
304 // Explict stack for pseudo-recursion, see `iter_nodes` above.
306 // Explict stack for pseudo-recursion, see `iter_nodes` above.
305 let mut stack = Vec::new();
307 let mut stack = Vec::new();
306 let mut iter = self.root.iter_mut();
308 let mut iter = self.root.iter_mut();
@@ -582,7 +584,7 b" impl<'on_disk> super::dispatch::Dirstate"
582 if node.copy_source.is_some() {
584 if node.copy_source.is_some() {
583 *count -= 1
585 *count -= 1
584 }
586 }
585 node.copy_source.take()
587 node.copy_source.take().map(Cow::into_owned)
586 })
588 })
587 }
589 }
588
590
@@ -595,7 +597,7 b" impl<'on_disk> super::dispatch::Dirstate"
595 if node.copy_source.is_none() {
597 if node.copy_source.is_none() {
596 self.nodes_with_copy_source_count += 1
598 self.nodes_with_copy_source_count += 1
597 }
599 }
598 node.copy_source.replace(value)
600 node.copy_source.replace(value.into()).map(Cow::into_owned)
599 }
601 }
600
602
601 fn len(&self) -> usize {
603 fn len(&self) -> usize {
General Comments 0
You need to be logged in to leave comments. Login now