diff rust/hg-core/src/revlog/mod.rs @ 50998:12c308c55e53

branching: merge stable into default
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 11 Oct 2023 02:02:46 +0200
parents 4c5f6e95df84 eccf7dc7c91e
children 532e74ad3ff6
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/mod.rs	Wed Jan 25 15:34:27 2023 +0100
+++ b/rust/hg-core/src/revlog/mod.rs	Wed Oct 11 02:02:46 2023 +0200
@@ -236,6 +236,16 @@
         data_path: Option<&Path>,
         use_nodemap: bool,
     ) -> Result<Self, HgError> {
+        Self::open_gen(store_vfs, index_path, data_path, use_nodemap, None)
+    }
+
+    fn open_gen(
+        store_vfs: &Vfs,
+        index_path: impl AsRef<Path>,
+        data_path: Option<&Path>,
+        use_nodemap: bool,
+        nodemap_for_test: Option<nodemap::NodeTree>,
+    ) -> Result<Self, HgError> {
         let index_path = index_path.as_ref();
         let index = {
             match store_vfs.mmap_open_opt(&index_path)? {
@@ -273,6 +283,8 @@
             )
         };
 
+        let nodemap = nodemap_for_test.or(nodemap);
+
         Ok(Revlog {
             index,
             data_bytes,
@@ -306,23 +318,13 @@
         &self,
         node: NodePrefix,
     ) -> Result<Revision, RevlogError> {
-        let looked_up = if let Some(nodemap) = &self.nodemap {
+        if let Some(nodemap) = &self.nodemap {
             nodemap
                 .find_bin(&self.index, node)?
                 .ok_or(RevlogError::InvalidRevision)
         } else {
             self.rev_from_node_no_persistent_nodemap(node)
-        };
-
-        if node.is_prefix_of(&NULL_NODE) {
-            return match looked_up {
-                Ok(_) => Err(RevlogError::AmbiguousPrefix),
-                Err(RevlogError::InvalidRevision) => Ok(NULL_REVISION),
-                res => res,
-            };
-        };
-
-        looked_up
+        }
     }
 
     /// Same as `rev_from_node`, without using a persistent nodemap
@@ -338,17 +340,23 @@
         // TODO: consider building a non-persistent nodemap in memory to
         // optimize these cases.
         let mut found_by_prefix = None;
-        for rev in (0..self.len()).rev() {
+        for rev in (-1..self.len() as BaseRevision).rev() {
             let rev = Revision(rev as BaseRevision);
-            let index_entry = self.index.get_entry(rev).ok_or_else(|| {
-                HgError::corrupted(
-                    "revlog references a revision not in the index",
-                )
-            })?;
-            if node == *index_entry.hash() {
+            let candidate_node = if rev == Revision(-1) {
+                NULL_NODE
+            } else {
+                let index_entry =
+                    self.index.get_entry(rev).ok_or_else(|| {
+                        HgError::corrupted(
+                            "revlog references a revision not in the index",
+                        )
+                    })?;
+                *index_entry.hash()
+            };
+            if node == candidate_node {
                 return Ok(rev);
             }
-            if node.is_prefix_of(index_entry.hash()) {
+            if node.is_prefix_of(&candidate_node) {
                 if found_by_prefix.is_some() {
                     return Err(RevlogError::AmbiguousPrefix);
                 }
@@ -913,7 +921,13 @@
             .flatten()
             .collect_vec();
         std::fs::write(temp.path().join("foo.i"), contents).unwrap();
-        let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap();
+
+        let mut idx = nodemap::tests::TestNtIndex::new();
+        idx.insert_node(Revision(0), node0).unwrap();
+        idx.insert_node(Revision(1), node1).unwrap();
+
+        let revlog =
+            Revlog::open_gen(&vfs, "foo.i", None, true, Some(idx.nt)).unwrap();
 
         // accessing the data shows the corruption
         revlog.get_entry(0.into()).unwrap().data().unwrap_err();