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