Mercurial > public > mercurial-scm > hg
diff rust/hg-core/src/revlog/index.rs @ 52173:1da6995835b4
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.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Wed, 31 Jul 2024 15:02:55 +0200 |
parents | 6f94dc3cf8cf |
children | bd8081e9fd62 |
line wrap: on
line diff
--- 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()); {