Mercurial > public > mercurial-scm > hg
changeset 52782:827889802d11
rust-pyo3-revlog: nodemap filling accessor
This follows closely the original version in `hg-cpython`,
with perhaps room for improvement to spare the caller with
obscure and scary calls to `except()`.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Wed, 25 Dec 2024 14:00:34 +0100 |
parents | 918239b55b3a |
children | 07740bd86fd9 |
files | rust/hg-pyo3/src/exceptions.rs rust/hg-pyo3/src/revlog/mod.rs |
diffstat | 2 files changed, 48 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-pyo3/src/exceptions.rs Wed Dec 25 13:37:26 2024 +0100 +++ b/rust/hg-pyo3/src/exceptions.rs Wed Dec 25 14:00:34 2024 +0100 @@ -54,7 +54,6 @@ mercurial_py_errors::RevlogError::new_err(e.to_string().into_bytes()) } -#[allow(dead_code)] pub fn nodemap_error(err: NodeMapError) -> PyErr { match err { NodeMapError::MultipleResults => {
--- a/rust/hg-pyo3/src/revlog/mod.rs Wed Dec 25 13:37:26 2024 +0100 +++ b/rust/hg-pyo3/src/revlog/mod.rs Wed Dec 25 14:00:34 2024 +0100 @@ -17,14 +17,15 @@ revlog::{ index::Index, inner_revlog::InnerRevlog as CoreInnerRevlog, nodemap::NodeTree as CoreNodeTree, options::RevlogOpenOptions, - RevlogType, + RevlogIndex, RevlogType, }, utils::files::get_path_from_bytes, vfs::FnCacheVfs, + BaseRevision, Revision, }; use crate::{ - exceptions::revlog_error_from_msg, + exceptions::{map_lock_error, nodemap_error, revlog_error_from_msg}, store::PyFnCache, util::{new_submodule, take_buffer_with_slice}, }; @@ -127,6 +128,51 @@ } } +impl InnerRevlog { + /// Fill a [`CoreNodeTree`] by doing a full iteration on the given + /// [`Index`] + /// + /// # Python exceptions + /// Raises `ValueError` if `nt` has existing data that is inconsistent + /// with `idx`. + fn fill_nodemap(idx: &Index, nt: &mut CoreNodeTree) -> PyResult<()> { + for r in 0..idx.len() { + let rev = Revision(r as BaseRevision); + // in this case node() won't ever return None + nt.insert(idx, idx.node(rev).expect("node should exist"), rev) + .map_err(nodemap_error)? + } + Ok(()) + } + + /// Return a working NodeTree of this InnerRevlog + /// + /// In case the NodeTree has not been initialized yet (in particular + /// not from persistent data at instantiation), it is created and + /// filled right away from the index. + /// + /// Technically, the returned NodeTree is still behind the lock of + /// the `nt` field, hence still wrapped in an [`Option`]. Callers + /// will need to take the lock and unwrap with `expect()`. + /// + /// # Python exceptions + /// The case mentioned in [`Self::fill_nodemap()`] cannot happen, as the + /// NodeTree is empty when it is called. + #[allow(dead_code)] + fn get_nodetree( + &self, + idx: &Index, + ) -> PyResult<&RwLock<Option<CoreNodeTree>>> { + if self.nt.read().map_err(map_lock_error)?.is_none() { + let readonly = Box::<Vec<_>>::default(); + let mut nt = CoreNodeTree::load_bytes(readonly, 0); + Self::fill_nodemap(idx, &mut nt)?; + self.nt.write().map_err(map_lock_error)?.replace(nt); + } + Ok(&self.nt) + } +} + pub fn init_module<'py>( py: Python<'py>, package: &str,