diff -r 5e12b6bfdd3e -r 73ddcedeaadf rust/hg-core/src/dirstate_tree/dirstate_map.rs --- 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>; +/// 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, 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, DirstateV2ParseError> { + ) -> Result, 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(), + ) } } }