diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c --- a/mercurial/cext/parsers.c +++ b/mercurial/cext/parsers.c @@ -668,7 +668,7 @@ void dirs_module_init(PyObject *mod); void manifest_module_init(PyObject *mod); void revlog_module_init(PyObject *mod); -static const int version = 19; +static const int version = 20; static void module_init(PyObject *mod) { diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -101,8 +101,10 @@ struct indexObjectStruct { int inlined; long entry_size; /* size of index headers. Differs in v1 v.s. v2 format */ - char format_version; /* size of index headers. Differs in v1 v.s. v2 - format */ + long rust_ext_compat; /* compatibility with being used in rust + extensions */ + char format_version; /* size of index headers. Differs in v1 v.s. v2 + format */ }; static Py_ssize_t index_length(const indexObject *self) @@ -2769,6 +2771,7 @@ static int index_init(indexObject *self, self->offsets = NULL; self->nodelen = 20; self->nullentry = NULL; + self->rust_ext_compat = 1; revlogv2 = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", kwlist, @@ -2941,6 +2944,8 @@ static PyGetSetDef index_getset[] = { static PyMemberDef index_members[] = { {"entry_size", T_LONG, offsetof(indexObject, entry_size), 0, "size of an index entry"}, + {"rust_ext_compat", T_LONG, offsetof(indexObject, rust_ext_compat), 0, + "size of an index entry"}, {NULL} /* Sentinel */ }; diff --git a/mercurial/policy.py b/mercurial/policy.py --- a/mercurial/policy.py +++ b/mercurial/policy.py @@ -80,7 +80,7 @@ def _importfrom(pkgname, modname): ('cext', 'bdiff'): 3, ('cext', 'mpatch'): 1, ('cext', 'osutil'): 4, - ('cext', 'parsers'): 19, + ('cext', 'parsers'): 20, } # map import request to other package or module diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -47,6 +47,8 @@ def offset_type(offset, type): class BaseIndexObject(object): + # Can I be passed to an algorithme implemented in Rust ? + rust_ext_compat = 0 # Format of an index entry according to Python's `struct` language index_format = revlog_constants.INDEX_ENTRY_V1 # Size of a C unsigned long long int, platform independent diff --git a/mercurial/revlogutils/revlogv0.py b/mercurial/revlogutils/revlogv0.py --- a/mercurial/revlogutils/revlogv0.py +++ b/mercurial/revlogutils/revlogv0.py @@ -42,6 +42,7 @@ def offset_type(offset, type): class revlogoldindex(list): + rust_ext_compat = 0 entry_size = INDEX_ENTRY_V0.size null_item = ( 0, diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,8 +11,8 @@ //! but this will take some time to get there. use cpython::{ - exc::ImportError, ObjectProtocol, PyClone, PyErr, PyObject, PyResult, - PyTuple, Python, PythonObject, + exc::ImportError, exc::TypeError, ObjectProtocol, PyClone, PyErr, + PyObject, PyResult, PyTuple, Python, PythonObject, }; use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; @@ -90,6 +90,13 @@ impl Index { ), )); } + let compat: u64 = index.getattr(py, "rust_ext_compat")?.extract(py)?; + if compat == 0 { + return Err(PyErr::new::( + py, + "index object not compatible with Rust", + )); + } Ok(Index { index, capi }) } diff --git a/rust/hg-cpython/src/revlog.rs b/rust/hg-cpython/src/revlog.rs --- a/rust/hg-cpython/src/revlog.rs +++ b/rust/hg-cpython/src/revlog.rs @@ -300,6 +300,11 @@ py_class!(pub class MixedIndex |py| { self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::(py) } + @property + def rust_ext_compat(&self) -> PyResult { + self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::(py) + } + }); impl MixedIndex {