diff -r 633408a0f2e2 -r 7eea2e4109ae rust/hg-cpython/src/revlog.rs --- a/rust/hg-cpython/src/revlog.rs Fri Oct 27 23:29:29 2023 +0200 +++ b/rust/hg-cpython/src/revlog.rs Fri Oct 27 22:11:05 2023 +0200 @@ -16,7 +16,7 @@ exc::{IndexError, ValueError}, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyInt, PyList, PyModule, PyObject, PyResult, PySet, PyString, PyTuple, Python, - PythonObject, ToPyObject, + PythonObject, ToPyObject, UnsafePyLeaked, }; use hg::{ errors::HgError, @@ -25,10 +25,11 @@ INDEX_ENTRY_SIZE, }, nodemap::{Block, NodeMapError, NodeTree}, - revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex}, - BaseRevision, Revision, UncheckedRevision, NULL_REVISION, + revlog::{nodemap::NodeMap, Graph, NodePrefix, RevlogError, RevlogIndex}, + BaseRevision, Node, Revision, UncheckedRevision, NULL_REVISION, }; use std::{cell::RefCell, collections::HashMap}; +use vcsgraph::graph::Graph as VCSGraph; /// Return a Struct implementing the Graph trait pub(crate) fn pyindex_to_graph( @@ -41,9 +42,64 @@ } } +pub struct PySharedIndex { + /// The underlying hg-core index + pub(crate) inner: &'static hg::index::Index, +} + +/// Return a Struct implementing the Graph trait +pub(crate) fn py_rust_index_to_graph( + py: Python, + index: PyObject, +) -> PyResult> { + let midx = index.extract::(py)?; + let leaked = midx.index(py).leak_immutable(); + Ok(unsafe { leaked.map(py, |idx| PySharedIndex { inner: idx }) }) +} + +impl Clone for PySharedIndex { + fn clone(&self) -> Self { + Self { inner: self.inner } + } +} + +impl Graph for PySharedIndex { + fn parents(&self, rev: Revision) -> Result<[Revision; 2], hg::GraphError> { + self.inner.parents(rev) + } +} + +impl VCSGraph for PySharedIndex { + fn parents( + &self, + rev: BaseRevision, + ) -> Result + { + // FIXME This trait should be reworked to decide between Revision + // and UncheckedRevision, get better errors names, etc. + match Graph::parents(self, Revision(rev)) { + Ok(parents) => { + Ok(vcsgraph::graph::Parents([parents[0].0, parents[1].0])) + } + Err(hg::GraphError::ParentOutOfRange(rev)) => { + Err(vcsgraph::graph::GraphReadError::KeyedInvalidKey(rev.0)) + } + } + } +} + +impl RevlogIndex for PySharedIndex { + fn len(&self) -> usize { + self.inner.len() + } + fn node(&self, rev: Revision) -> Option<&Node> { + self.inner.node(rev) + } +} + py_class!(pub class MixedIndex |py| { data cindex: RefCell; - data index: RefCell; + @shared data index: hg::index::Index; data nt: RefCell>; data docket: RefCell>; // Holds a reference to the mmap'ed persistent nodemap data @@ -668,17 +724,15 @@ Self::create_instance( py, RefCell::new(cindex::Index::new(py, cindex)?), - RefCell::new( - hg::index::Index::new( - bytes, - IndexHeader::parse(&header.to_be_bytes()) - .expect("default header is broken") - .unwrap(), - ) - .map_err(|e| { - revlog_error_with_msg(py, e.to_string().as_bytes()) - })?, - ), + hg::index::Index::new( + bytes, + IndexHeader::parse(&header.to_be_bytes()) + .expect("default header is broken") + .unwrap(), + ) + .map_err(|e| { + revlog_error_with_msg(py, e.to_string().as_bytes()) + })?, RefCell::new(None), RefCell::new(None), RefCell::new(None),