rust/hg-core/src/dirstate_tree/dirstate_map.rs
changeset 47347 73ddcedeaadf
parent 47337 0654b3b3d2b5
child 47348 a4de570e61fa
--- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Fri May 28 12:16:14 2021 +0200
+++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs	Fri May 28 20:07:27 2021 +0200
@@ -46,6 +46,13 @@
 /// string prefix.
 pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>;
 
+/// Similar to `&'tree Cow<'on_disk, HgPath>`, but can also be returned
+/// for on-disk nodes that don’t actually have a `Cow` to borrow.
+pub(super) enum BorrowedPath<'tree, 'on_disk> {
+    InMemory(&'tree HgPathBuf),
+    OnDisk(&'on_disk HgPath),
+}
+
 pub(super) enum ChildNodes<'on_disk> {
     InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>),
     OnDisk(&'on_disk [on_disk::Node]),
@@ -61,6 +68,26 @@
     OnDisk(&'on_disk on_disk::Node),
 }
 
+impl<'tree, 'on_disk> BorrowedPath<'tree, 'on_disk> {
+    pub fn detach_from_tree(&self) -> Cow<'on_disk, HgPath> {
+        match *self {
+            BorrowedPath::InMemory(in_memory) => Cow::Owned(in_memory.clone()),
+            BorrowedPath::OnDisk(on_disk) => Cow::Borrowed(on_disk),
+        }
+    }
+}
+
+impl<'tree, 'on_disk> std::ops::Deref for BorrowedPath<'tree, 'on_disk> {
+    type Target = HgPath;
+
+    fn deref(&self) -> &HgPath {
+        match *self {
+            BorrowedPath::InMemory(in_memory) => in_memory,
+            BorrowedPath::OnDisk(on_disk) => on_disk,
+        }
+    }
+}
+
 impl Default for ChildNodes<'_> {
     fn default() -> Self {
         ChildNodes::InMemory(Default::default())
@@ -210,15 +237,19 @@
         }
     }
 
-    /// Returns a `Cow` that can borrow 'on_disk but is detached from 'tree
-    pub(super) fn full_path_cow(
+    /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk,
+    /// HgPath>` detached from `'tree`
+    pub(super) fn full_path_borrowed(
         &self,
         on_disk: &'on_disk [u8],
-    ) -> Result<Cow<'on_disk, HgPath>, DirstateV2ParseError> {
+    ) -> Result<BorrowedPath<'tree, 'on_disk>, DirstateV2ParseError> {
         match self {
-            NodeRef::InMemory(path, _node) => Ok(path.full_path().clone()),
+            NodeRef::InMemory(path, _node) => match path.full_path() {
+                Cow::Borrowed(on_disk) => Ok(BorrowedPath::OnDisk(on_disk)),
+                Cow::Owned(in_memory) => Ok(BorrowedPath::InMemory(in_memory)),
+            },
             NodeRef::OnDisk(node) => {
-                Ok(Cow::Borrowed(node.full_path(on_disk)?))
+                Ok(BorrowedPath::OnDisk(node.full_path(on_disk)?))
             }
         }
     }
@@ -819,7 +850,10 @@
                     node.copy_source(self.on_disk)?,
                 );
                 if entry.mtime_is_ambiguous(now) {
-                    ambiguous_mtimes.push(node.full_path_cow(self.on_disk)?)
+                    ambiguous_mtimes.push(
+                        node.full_path_borrowed(self.on_disk)?
+                            .detach_from_tree(),
+                    )
                 }
             }
         }
@@ -855,7 +889,10 @@
             let node = node?;
             if let Some(entry) = node.entry()? {
                 if entry.mtime_is_ambiguous(now) {
-                    paths.push(node.full_path_cow(self.on_disk)?)
+                    paths.push(
+                        node.full_path_borrowed(self.on_disk)?
+                            .detach_from_tree(),
+                    )
                 }
             }
         }