44 /// 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 |
45 /// names. However `HashMap` would waste time always re-hashing the same |
45 /// names. However `HashMap` would waste time always re-hashing the same |
46 /// string prefix. |
46 /// string prefix. |
47 pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>; |
47 pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>; |
48 |
48 |
|
49 /// Similar to `&'tree Cow<'on_disk, HgPath>`, but can also be returned |
|
50 /// for on-disk nodes that don’t actually have a `Cow` to borrow. |
|
51 pub(super) enum BorrowedPath<'tree, 'on_disk> { |
|
52 InMemory(&'tree HgPathBuf), |
|
53 OnDisk(&'on_disk HgPath), |
|
54 } |
|
55 |
49 pub(super) enum ChildNodes<'on_disk> { |
56 pub(super) enum ChildNodes<'on_disk> { |
50 InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>), |
57 InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>), |
51 OnDisk(&'on_disk [on_disk::Node]), |
58 OnDisk(&'on_disk [on_disk::Node]), |
52 } |
59 } |
53 |
60 |
57 } |
64 } |
58 |
65 |
59 pub(super) enum NodeRef<'tree, 'on_disk> { |
66 pub(super) enum NodeRef<'tree, 'on_disk> { |
60 InMemory(&'tree NodeKey<'on_disk>, &'tree Node<'on_disk>), |
67 InMemory(&'tree NodeKey<'on_disk>, &'tree Node<'on_disk>), |
61 OnDisk(&'on_disk on_disk::Node), |
68 OnDisk(&'on_disk on_disk::Node), |
|
69 } |
|
70 |
|
71 impl<'tree, 'on_disk> BorrowedPath<'tree, 'on_disk> { |
|
72 pub fn detach_from_tree(&self) -> Cow<'on_disk, HgPath> { |
|
73 match *self { |
|
74 BorrowedPath::InMemory(in_memory) => Cow::Owned(in_memory.clone()), |
|
75 BorrowedPath::OnDisk(on_disk) => Cow::Borrowed(on_disk), |
|
76 } |
|
77 } |
|
78 } |
|
79 |
|
80 impl<'tree, 'on_disk> std::ops::Deref for BorrowedPath<'tree, 'on_disk> { |
|
81 type Target = HgPath; |
|
82 |
|
83 fn deref(&self) -> &HgPath { |
|
84 match *self { |
|
85 BorrowedPath::InMemory(in_memory) => in_memory, |
|
86 BorrowedPath::OnDisk(on_disk) => on_disk, |
|
87 } |
|
88 } |
62 } |
89 } |
63 |
90 |
64 impl Default for ChildNodes<'_> { |
91 impl Default for ChildNodes<'_> { |
65 fn default() -> Self { |
92 fn default() -> Self { |
66 ChildNodes::InMemory(Default::default()) |
93 ChildNodes::InMemory(Default::default()) |
208 NodeRef::InMemory(path, _node) => Ok(path.full_path()), |
235 NodeRef::InMemory(path, _node) => Ok(path.full_path()), |
209 NodeRef::OnDisk(node) => node.full_path(on_disk), |
236 NodeRef::OnDisk(node) => node.full_path(on_disk), |
210 } |
237 } |
211 } |
238 } |
212 |
239 |
213 /// Returns a `Cow` that can borrow 'on_disk but is detached from 'tree |
240 /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk, |
214 pub(super) fn full_path_cow( |
241 /// HgPath>` detached from `'tree` |
|
242 pub(super) fn full_path_borrowed( |
215 &self, |
243 &self, |
216 on_disk: &'on_disk [u8], |
244 on_disk: &'on_disk [u8], |
217 ) -> Result<Cow<'on_disk, HgPath>, DirstateV2ParseError> { |
245 ) -> Result<BorrowedPath<'tree, 'on_disk>, DirstateV2ParseError> { |
218 match self { |
246 match self { |
219 NodeRef::InMemory(path, _node) => Ok(path.full_path().clone()), |
247 NodeRef::InMemory(path, _node) => match path.full_path() { |
|
248 Cow::Borrowed(on_disk) => Ok(BorrowedPath::OnDisk(on_disk)), |
|
249 Cow::Owned(in_memory) => Ok(BorrowedPath::InMemory(in_memory)), |
|
250 }, |
220 NodeRef::OnDisk(node) => { |
251 NodeRef::OnDisk(node) => { |
221 Ok(Cow::Borrowed(node.full_path(on_disk)?)) |
252 Ok(BorrowedPath::OnDisk(node.full_path(on_disk)?)) |
222 } |
253 } |
223 } |
254 } |
224 } |
255 } |
225 |
256 |
226 pub(super) fn base_name( |
257 pub(super) fn base_name( |
817 size += packed_entry_size( |
848 size += packed_entry_size( |
818 node.full_path(self.on_disk)?, |
849 node.full_path(self.on_disk)?, |
819 node.copy_source(self.on_disk)?, |
850 node.copy_source(self.on_disk)?, |
820 ); |
851 ); |
821 if entry.mtime_is_ambiguous(now) { |
852 if entry.mtime_is_ambiguous(now) { |
822 ambiguous_mtimes.push(node.full_path_cow(self.on_disk)?) |
853 ambiguous_mtimes.push( |
|
854 node.full_path_borrowed(self.on_disk)? |
|
855 .detach_from_tree(), |
|
856 ) |
823 } |
857 } |
824 } |
858 } |
825 } |
859 } |
826 self.clear_known_ambiguous_mtimes(&ambiguous_mtimes)?; |
860 self.clear_known_ambiguous_mtimes(&ambiguous_mtimes)?; |
827 |
861 |
853 let mut paths = Vec::new(); |
887 let mut paths = Vec::new(); |
854 for node in self.iter_nodes() { |
888 for node in self.iter_nodes() { |
855 let node = node?; |
889 let node = node?; |
856 if let Some(entry) = node.entry()? { |
890 if let Some(entry) = node.entry()? { |
857 if entry.mtime_is_ambiguous(now) { |
891 if entry.mtime_is_ambiguous(now) { |
858 paths.push(node.full_path_cow(self.on_disk)?) |
892 paths.push( |
|
893 node.full_path_borrowed(self.on_disk)? |
|
894 .detach_from_tree(), |
|
895 ) |
859 } |
896 } |
860 } |
897 } |
861 } |
898 } |
862 // Borrow of `self` ends here since we collect cloned paths |
899 // Borrow of `self` ends here since we collect cloned paths |
863 |
900 |