# HG changeset patch # User Georges Racinet # Date 1698572874 -3600 # Node ID 578c049f0408aa969c976efa617963198da7b11f # Parent 59d81768ad6d1252a2fc9096fa62655d2379d3f7 rust-index: using `hg::index::Index` in `hg-cpython::dagops` Hooking `headrevs` to the Rust index is straightforward as long as we go the `PySharedRef` way. Direct attempts of obtaining a reference to the inner `hg::index::Index` fail for lifetime reasons: the reference is bound to the GIL, yet the `as_set` local variable is considered to be static (the borrow checker clearly does not realize or care that this set only stores `Revision` values). In `rank()`, the chosen solution is the simplest as far as `hg-cpython` is concerned, but it has the defect of removing an implementation that would be easily adaptable if the core index did implement `RankedGraph` (returning the same error as long as only `REVLOGV1` is supported), but that would introduce a direct dependency of `hg-core` on the ``vcsgraph` crate. diff -r 59d81768ad6d -r 578c049f0408 rust/hg-cpython/src/dagops.rs --- a/rust/hg-cpython/src/dagops.rs Sat Oct 28 22:50:10 2023 +0200 +++ b/rust/hg-cpython/src/dagops.rs Sun Oct 29 10:47:54 2023 +0100 @@ -15,10 +15,9 @@ use hg::dagops; use hg::Revision; use std::collections::HashSet; -use vcsgraph::ancestors::node_rank; -use vcsgraph::graph::{Parents, Rank}; +use vcsgraph::graph::Rank; -use crate::revlog::pyindex_to_graph; +use crate::revlog::py_rust_index_to_graph; /// Using the the `index`, return heads out of any Python iterable of Revisions /// @@ -28,23 +27,33 @@ index: PyObject, revs: PyObject, ) -> PyResult> { - let index = pyindex_to_graph(py, index)?; - let mut as_set: HashSet = rev_pyiter_collect(py, &revs, &index)?; - dagops::retain_heads(&index, &mut as_set) + let py_leaked = py_rust_index_to_graph(py, index)?; + let index = &*unsafe { py_leaked.try_borrow(py)? }; + let mut as_set: HashSet = rev_pyiter_collect(py, &revs, index)?; + dagops::retain_heads(index, &mut as_set) .map_err(|e| GraphError::pynew(py, e))?; Ok(as_set.into_iter().map(Into::into).collect()) } /// Computes the rank, i.e. the number of ancestors including itself, /// of a node represented by its parents. +/// +/// Currently, the pure Rust index supports only the REVLOGV1 format, hence +/// the only possible return value is that the rank is unknown. +/// +/// References: +/// - C implementation, function `index_fast_rank()`. +/// - `impl vcsgraph::graph::RankedGraph for Index` in `crate::cindex`. pub fn rank( py: Python, - index: PyObject, - p1r: PyRevision, - p2r: PyRevision, + _index: PyObject, + _p1r: PyRevision, + _p2r: PyRevision, ) -> PyResult { - node_rank(&pyindex_to_graph(py, index)?, &Parents([p1r.0, p2r.0])) - .map_err(|e| GraphError::pynew_from_vcsgraph(py, e)) + Err(GraphError::pynew_from_vcsgraph( + py, + vcsgraph::graph::GraphReadError::InconsistentGraphData, + )) } /// Create the module, with `__package__` given from parent diff -r 59d81768ad6d -r 578c049f0408 tests/test-rust-ancestor.py --- a/tests/test-rust-ancestor.py Sat Oct 28 22:50:10 2023 +0200 +++ b/tests/test-rust-ancestor.py Sun Oct 29 10:47:54 2023 +0100 @@ -157,7 +157,7 @@ self.assertEqual(exc.args, ('InvalidRevision', wdirrev)) def testheadrevs(self): - idx = self.parseindex() + idx = self.parserustindex() self.assertEqual(dagop.headrevs(idx, [1, 2, 3]), {3})