Mercurial > hg
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 { |