comparison rust/hg-core/src/revlog/index.rs @ 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 6f94dc3cf8cf
children bd8081e9fd62
comparison
equal deleted inserted replaced
52176:72bc29f01570 52177:1da6995835b4
5 5
6 use bitvec::prelude::*; 6 use bitvec::prelude::*;
7 use byteorder::{BigEndian, ByteOrder}; 7 use byteorder::{BigEndian, ByteOrder};
8 use bytes_cast::{unaligned, BytesCast}; 8 use bytes_cast::{unaligned, BytesCast};
9 9
10 use super::REVIDX_KNOWN_FLAGS; 10 use super::{NodePrefix, REVIDX_KNOWN_FLAGS};
11 use crate::errors::HgError; 11 use crate::errors::HgError;
12 use crate::node::{NODE_BYTES_LENGTH, NULL_NODE, STORED_NODE_ID_BYTES}; 12 use crate::node::{NODE_BYTES_LENGTH, NULL_NODE, STORED_NODE_ID_BYTES};
13 use crate::revlog::node::Node; 13 use crate::revlog::node::Node;
14 use crate::revlog::{Revision, NULL_REVISION}; 14 use crate::revlog::{Revision, NULL_REVISION};
15 use crate::{ 15 use crate::{
413 .expect("inline should have offsets") 413 .expect("inline should have offsets")
414 .len() 414 .len()
415 } else { 415 } else {
416 self.bytes.len() / INDEX_ENTRY_SIZE 416 self.bytes.len() / INDEX_ENTRY_SIZE
417 } 417 }
418 }
419
420 /// Same as `rev_from_node`, without using a persistent nodemap
421 ///
422 /// This is used as fallback when a persistent nodemap is not present.
423 /// This happens when the persistent-nodemap experimental feature is not
424 /// enabled, or for small revlogs.
425 pub fn rev_from_node_no_persistent_nodemap(
426 &self,
427 node: NodePrefix,
428 ) -> Result<Revision, RevlogError> {
429 // Linear scan of the revlog
430 // TODO: consider building a non-persistent nodemap in memory to
431 // optimize these cases.
432 let mut found_by_prefix = None;
433 for rev in (-1..self.len() as BaseRevision).rev() {
434 let rev = Revision(rev as BaseRevision);
435 let candidate_node = if rev == Revision(-1) {
436 NULL_NODE
437 } else {
438 let index_entry = self.get_entry(rev).ok_or_else(|| {
439 HgError::corrupted(
440 "revlog references a revision not in the index",
441 )
442 })?;
443 *index_entry.hash()
444 };
445 if node == candidate_node {
446 return Ok(rev);
447 }
448 if node.is_prefix_of(&candidate_node) {
449 if found_by_prefix.is_some() {
450 return Err(RevlogError::AmbiguousPrefix);
451 }
452 found_by_prefix = Some(rev)
453 }
454 }
455 found_by_prefix
456 .ok_or_else(|| RevlogError::InvalidRevision(format!("{:x}", node)))
418 } 457 }
419 458
420 pub fn get_offsets(&self) -> RwLockReadGuard<Option<Vec<usize>>> { 459 pub fn get_offsets(&self) -> RwLockReadGuard<Option<Vec<usize>>> {
421 assert!(self.is_inline()); 460 assert!(self.is_inline());
422 { 461 {