rust-revlog: move non-persistent-nodemap rev lookup to the index
authorRaphaël Gomès <rgomes@octobus.net>
Wed, 31 Jul 2024 15:02:55 +0200
changeset 52177 1da6995835b4
parent 52176 72bc29f01570
child 52178 bcd4962e0df9
rust-revlog: move non-persistent-nodemap rev lookup to the index It only uses index features and does not need to be on the revlog. A later patch will make use of this function from a different context.
rust/hg-core/src/revlog/index.rs
rust/hg-core/src/revlog/mod.rs
--- a/rust/hg-core/src/revlog/index.rs	Mon Jul 29 20:39:34 2024 +0200
+++ b/rust/hg-core/src/revlog/index.rs	Wed Jul 31 15:02:55 2024 +0200
@@ -7,7 +7,7 @@
 use byteorder::{BigEndian, ByteOrder};
 use bytes_cast::{unaligned, BytesCast};
 
-use super::REVIDX_KNOWN_FLAGS;
+use super::{NodePrefix, REVIDX_KNOWN_FLAGS};
 use crate::errors::HgError;
 use crate::node::{NODE_BYTES_LENGTH, NULL_NODE, STORED_NODE_ID_BYTES};
 use crate::revlog::node::Node;
@@ -417,6 +417,45 @@
         }
     }
 
+    /// Same as `rev_from_node`, without using a persistent nodemap
+    ///
+    /// This is used as fallback when a persistent nodemap is not present.
+    /// This happens when the persistent-nodemap experimental feature is not
+    /// enabled, or for small revlogs.
+    pub fn rev_from_node_no_persistent_nodemap(
+        &self,
+        node: NodePrefix,
+    ) -> Result<Revision, RevlogError> {
+        // Linear scan of the revlog
+        // TODO: consider building a non-persistent nodemap in memory to
+        // optimize these cases.
+        let mut found_by_prefix = None;
+        for rev in (-1..self.len() as BaseRevision).rev() {
+            let rev = Revision(rev as BaseRevision);
+            let candidate_node = if rev == Revision(-1) {
+                NULL_NODE
+            } else {
+                let index_entry = self.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(&candidate_node) {
+                if found_by_prefix.is_some() {
+                    return Err(RevlogError::AmbiguousPrefix);
+                }
+                found_by_prefix = Some(rev)
+            }
+        }
+        found_by_prefix
+            .ok_or_else(|| RevlogError::InvalidRevision(format!("{:x}", node)))
+    }
+
     pub fn get_offsets(&self) -> RwLockReadGuard<Option<Vec<usize>>> {
         assert!(self.is_inline());
         {
--- a/rust/hg-core/src/revlog/mod.rs	Mon Jul 29 20:39:34 2024 +0200
+++ b/rust/hg-core/src/revlog/mod.rs	Wed Jul 31 15:02:55 2024 +0200
@@ -363,50 +363,10 @@
                 .find_bin(self.index(), node)?
                 .ok_or(RevlogError::InvalidRevision(format!("{:x}", node)))
         } else {
-            self.rev_from_node_no_persistent_nodemap(node)
+            self.index().rev_from_node_no_persistent_nodemap(node)
         }
     }
 
-    /// Same as `rev_from_node`, without using a persistent nodemap
-    ///
-    /// This is used as fallback when a persistent nodemap is not present.
-    /// This happens when the persistent-nodemap experimental feature is not
-    /// enabled, or for small revlogs.
-    fn rev_from_node_no_persistent_nodemap(
-        &self,
-        node: NodePrefix,
-    ) -> Result<Revision, RevlogError> {
-        // Linear scan of the revlog
-        // TODO: consider building a non-persistent nodemap in memory to
-        // optimize these cases.
-        let mut found_by_prefix = None;
-        for rev in (-1..self.len() as BaseRevision).rev() {
-            let rev = Revision(rev as BaseRevision);
-            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(&candidate_node) {
-                if found_by_prefix.is_some() {
-                    return Err(RevlogError::AmbiguousPrefix);
-                }
-                found_by_prefix = Some(rev)
-            }
-        }
-        found_by_prefix
-            .ok_or(RevlogError::InvalidRevision(format!("{:x}", node)))
-    }
-
     /// Returns whether the given revision exists in this revlog.
     pub fn has_rev(&self, rev: UncheckedRevision) -> bool {
         self.index().check_revision(rev).is_some()