revlog: signal which revlog index are compatible with Rust
authorPierre-Yves David <pierre-yves.david@octobus.net>
Tue, 04 May 2021 14:16:26 +0200
changeset 47268 9d1a8829f959
parent 47267 55d280bc59fa
child 47269 6be2a7ca4b1d
revlog: signal which revlog index are compatible with Rust Otherwise, Rust may treat python object like `cindex` object, leading to trouble. The new attribute is an integer because I expect we might need a flag field in the future. As a start we get the rust code to raise a clear TypeError. We will use the information in a smarter way in the next changesets. Differential Revision: https://phab.mercurial-scm.org/D10665
mercurial/cext/parsers.c
mercurial/cext/revlog.c
mercurial/policy.py
mercurial/pure/parsers.py
mercurial/revlogutils/revlogv0.py
rust/hg-cpython/src/cindex.rs
rust/hg-cpython/src/revlog.rs
--- a/mercurial/cext/parsers.c	Tue May 04 11:19:48 2021 +0200
+++ b/mercurial/cext/parsers.c	Tue May 04 14:16:26 2021 +0200
@@ -668,7 +668,7 @@
 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)
 {
--- a/mercurial/cext/revlog.c	Tue May 04 11:19:48 2021 +0200
+++ b/mercurial/cext/revlog.c	Tue May 04 14:16:26 2021 +0200
@@ -101,8 +101,10 @@
 	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 @@
 	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 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 */
 };
 
--- a/mercurial/policy.py	Tue May 04 11:19:48 2021 +0200
+++ b/mercurial/policy.py	Tue May 04 14:16:26 2021 +0200
@@ -80,7 +80,7 @@
     ('cext', 'bdiff'): 3,
     ('cext', 'mpatch'): 1,
     ('cext', 'osutil'): 4,
-    ('cext', 'parsers'): 19,
+    ('cext', 'parsers'): 20,
 }
 
 # map import request to other package or module
--- a/mercurial/pure/parsers.py	Tue May 04 11:19:48 2021 +0200
+++ b/mercurial/pure/parsers.py	Tue May 04 14:16:26 2021 +0200
@@ -47,6 +47,8 @@
 
 
 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
--- a/mercurial/revlogutils/revlogv0.py	Tue May 04 11:19:48 2021 +0200
+++ b/mercurial/revlogutils/revlogv0.py	Tue May 04 14:16:26 2021 +0200
@@ -42,6 +42,7 @@
 
 
 class revlogoldindex(list):
+    rust_ext_compat = 0
     entry_size = INDEX_ENTRY_V0.size
     null_item = (
         0,
--- a/rust/hg-cpython/src/cindex.rs	Tue May 04 11:19:48 2021 +0200
+++ b/rust/hg-cpython/src/cindex.rs	Tue May 04 14:16:26 2021 +0200
@@ -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 @@
                 ),
             ));
         }
+        let compat: u64 = index.getattr(py, "rust_ext_compat")?.extract(py)?;
+        if compat == 0 {
+            return Err(PyErr::new::<TypeError, _>(
+                py,
+                "index object not compatible with Rust",
+            ));
+        }
         Ok(Index { index, capi })
     }
 
--- a/rust/hg-cpython/src/revlog.rs	Tue May 04 11:19:48 2021 +0200
+++ b/rust/hg-cpython/src/revlog.rs	Tue May 04 14:16:26 2021 +0200
@@ -300,6 +300,11 @@
         self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::<PyInt>(py)
     }
 
+    @property
+    def rust_ext_compat(&self) -> PyResult<PyInt> {
+        self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py)
+    }
+
 });
 
 impl MixedIndex {