--- 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());
{