On the long run we will want to implement the Graph trait directly in Rust, but
for now we take the path with the least amount of change to focus on the coming
persistent NodeMap code.
We test this new code through with the lazy ancestors code.
Alphare |
hg-reviewers |
On the long run we will want to implement the Graph trait directly in Rust, but
for now we take the path with the least amount of change to focus on the coming
persistent NodeMap code.
We test this new code through with the lazy ancestors code.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, PythonObject, | ObjectProtocol, PyClone, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, PythonObject, | ||||
ToPyObject, | ToPyObject, | ||||
}; | }; | ||||
use hg::Revision; | use hg::Revision; | ||||
use std::cell::RefCell; | use std::cell::RefCell; | ||||
/// Return a Struct implementing the Graph trait | /// Return a Struct implementing the Graph trait | ||||
pub(crate) fn pyindex_to_graph(py: Python, index: PyObject) -> PyResult<cindex::Index> { | pub(crate) fn pyindex_to_graph(py: Python, index: PyObject) -> PyResult<cindex::Index> { | ||||
cindex::Index::new(py, index) | match index.extract::<MixedIndex>(py) { | ||||
Ok(midx) => Ok(midx.clone_cindex(py)), | |||||
Err(_) => cindex::Index::new(py, index), | |||||
} | |||||
} | } | ||||
py_class!(pub class MixedIndex |py| { | py_class!(pub class MixedIndex |py| { | ||||
data cindex: RefCell<cindex::Index>; | data cindex: RefCell<cindex::Index>; | ||||
def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> { | def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> { | ||||
Self::create_instance(py, RefCell::new( | Self::create_instance(py, RefCell::new( | ||||
cindex::Index::new(py, cindex)?)) | cindex::Index::new(py, cindex)?)) |
from __future__ import absolute_import | from __future__ import absolute_import | ||||
import unittest | import unittest | ||||
try: | try: | ||||
from mercurial import rustext | from mercurial import rustext | ||||
rustext.__name__ # trigger immediate actual import | rustext.__name__ # trigger immediate actual import | ||||
except ImportError: | except ImportError: | ||||
rustext = None | rustext = None | ||||
else: | else: | ||||
from mercurial.rustext import revlog | from mercurial.rustext import revlog | ||||
# this would fail already without appropriate ancestor.__package__ | |||||
from mercurial.rustext.ancestor import LazyAncestors | |||||
from mercurial.testing import revlog as revlogtesting | from mercurial.testing import revlog as revlogtesting | ||||
@unittest.skipIf( | @unittest.skipIf( | ||||
rustext is None, "rustext module revlog relies on is not available", | rustext is None, "rustext module revlog relies on is not available", | ||||
) | ) | ||||
class RustRevlogIndexTest(revlogtesting.RevlogBasedTestBase): | class RustRevlogIndexTest(revlogtesting.RevlogBasedTestBase): | ||||
def test_heads(self): | def test_heads(self): | ||||
idx = self.parseindex() | idx = self.parseindex() | ||||
rustidx = revlog.MixedIndex(idx) | rustidx = revlog.MixedIndex(idx) | ||||
self.assertEqual(rustidx.headrevs(), idx.headrevs()) | self.assertEqual(rustidx.headrevs(), idx.headrevs()) | ||||
def test_len(self): | def test_len(self): | ||||
idx = self.parseindex() | idx = self.parseindex() | ||||
rustidx = revlog.MixedIndex(idx) | rustidx = revlog.MixedIndex(idx) | ||||
self.assertEqual(len(rustidx), len(idx)) | self.assertEqual(len(rustidx), len(idx)) | ||||
def test_ancestors(self): | |||||
idx = self.parseindex() | |||||
rustidx = revlog.MixedIndex(idx) | |||||
lazy = LazyAncestors(rustidx, [3], 0, True) | |||||
# we have two more references to the index: | |||||
# - in its inner iterator for __contains__ and __bool__ | |||||
# - in the LazyAncestors instance itself (to spawn new iterators) | |||||
self.assertTrue(2 in lazy) | |||||
self.assertTrue(bool(lazy)) | |||||
self.assertEqual(list(lazy), [3, 2, 1, 0]) | |||||
# a second time to validate that we spawn new iterators | |||||
self.assertEqual(list(lazy), [3, 2, 1, 0]) | |||||
# let's check bool for an empty one | |||||
self.assertFalse(LazyAncestors(idx, [0], 0, False)) | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
import silenttestrunner | import silenttestrunner | ||||
silenttestrunner.main(__name__) | silenttestrunner.main(__name__) |