Mercurial > hg
changeset 52177: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 | 72bc29f01570 |
children | bcd4962e0df9 |
files | rust/hg-core/src/revlog/index.rs rust/hg-core/src/revlog/mod.rs |
diffstat | 2 files changed, 41 insertions(+), 42 deletions(-) [+] |
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()); {
--- 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()