dirstate: Use the Rust implementation of DirstateItem when Rust is enabled
authorSimon Sapin <simon.sapin@octobus.net>
Wed, 22 Sep 2021 11:33:29 +0200
changeset 48059 d5528ac9b4f2
parent 48058 3e69bef2031a
child 48060 32ef647821b2
dirstate: Use the Rust implementation of DirstateItem when Rust is enabled … instead of the C implementation, with C/Rust conversions at the FFI boundary Differential Revision: https://phab.mercurial-scm.org/D11486
mercurial/cext/parsers.c
mercurial/dirstate.py
mercurial/dirstatemap.py
rust/hg-cpython/src/dirstate.rs
rust/hg-cpython/src/dirstate/dirstate_map.rs
--- a/mercurial/cext/parsers.c	Wed Sep 22 11:28:52 2021 +0200
+++ b/mercurial/cext/parsers.c	Wed Sep 22 11:33:29 2021 +0200
@@ -1233,7 +1233,6 @@
 
 static void module_init(PyObject *mod)
 {
-	PyObject *capsule = NULL;
 	PyModule_AddIntConstant(mod, "version", version);
 
 	/* This module constant has two purposes.  First, it lets us unit test
@@ -1250,12 +1249,6 @@
 	manifest_module_init(mod);
 	revlog_module_init(mod);
 
-	capsule = PyCapsule_New(
-	    dirstate_item_from_v1_data,
-	    "mercurial.cext.parsers.make_dirstate_item_CAPI", NULL);
-	if (capsule != NULL)
-		PyModule_AddObject(mod, "make_dirstate_item_CAPI", capsule);
-
 	if (PyType_Ready(&dirstateItemType) < 0) {
 		return;
 	}
--- a/mercurial/dirstate.py	Wed Sep 22 11:28:52 2021 +0200
+++ b/mercurial/dirstate.py	Wed Sep 22 11:33:29 2021 +0200
@@ -45,7 +45,7 @@
 filecache = scmutil.filecache
 _rangemask = dirstatemap.rangemask
 
-DirstateItem = parsers.DirstateItem
+DirstateItem = dirstatemap.DirstateItem
 
 
 class repocache(filecache):
--- a/mercurial/dirstatemap.py	Wed Sep 22 11:28:52 2021 +0200
+++ b/mercurial/dirstatemap.py	Wed Sep 22 11:33:29 2021 +0200
@@ -27,7 +27,10 @@
 
 propertycache = util.propertycache
 
-DirstateItem = parsers.DirstateItem
+if rustmod is None:
+    DirstateItem = parsers.DirstateItem
+else:
+    DirstateItem = rustmod.DirstateItem
 
 rangemask = 0x7FFFFFFF
 
--- a/rust/hg-cpython/src/dirstate.rs	Wed Sep 22 11:28:52 2021 +0200
+++ b/rust/hg-cpython/src/dirstate.rs	Wed Sep 22 11:33:29 2021 +0200
@@ -22,51 +22,8 @@
     },
     exceptions,
 };
-use cpython::{
-    PyBytes, PyDict, PyErr, PyList, PyModule, PyObject, PyResult, Python,
-};
+use cpython::{PyBytes, PyDict, PyList, PyModule, PyObject, PyResult, Python};
 use hg::dirstate_tree::on_disk::V2_FORMAT_MARKER;
-use hg::DirstateEntry;
-use libc::{c_char, c_int};
-
-// C code uses a custom `dirstate_tuple` type, checks in multiple instances
-// for this type, and raises a Python `Exception` if the check does not pass.
-// Because this type differs only in name from the regular Python tuple, it
-// would be a good idea in the near future to remove it entirely to allow
-// for a pure Python tuple of the same effective structure to be used,
-// rendering this type and the capsule below useless.
-py_capsule_fn!(
-    from mercurial.cext.parsers import make_dirstate_item_CAPI
-        as make_dirstate_item_capi
-        signature (
-            state: c_char,
-            mode: c_int,
-            size: c_int,
-            mtime: c_int,
-        ) -> *mut RawPyObject
-);
-
-pub fn make_dirstate_item(
-    py: Python,
-    entry: &DirstateEntry,
-) -> PyResult<PyObject> {
-    // Explicitly go through u8 first, then cast to platform-specific `c_char`
-    // because Into<u8> has a specific implementation while `as c_char` would
-    // just do a naive enum cast.
-    let state_code: u8 = entry.state().into();
-
-    let make = make_dirstate_item_capi::retrieve(py)?;
-    let maybe_obj = unsafe {
-        let ptr = make(
-            state_code as c_char,
-            entry.mode(),
-            entry.size(),
-            entry.mtime(),
-        );
-        PyObject::from_owned_ptr_opt(py, ptr)
-    };
-    maybe_obj.ok_or_else(|| PyErr::fetch(py))
-}
 
 /// Create the module, with `__package__` given from parent
 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs	Wed Sep 22 11:28:52 2021 +0200
+++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs	Wed Sep 22 11:33:29 2021 +0200
@@ -19,7 +19,7 @@
 
 use crate::{
     dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
-    dirstate::make_dirstate_item,
+    dirstate::item::DirstateItem,
     dirstate::non_normal_entries::{
         NonNormalEntries, NonNormalEntriesIterator,
     },
@@ -123,7 +123,7 @@
             .map_err(|e| v2_error(py, e))?
         {
             Some(entry) => {
-                Ok(Some(make_dirstate_item(py, &entry)?))
+                Ok(Some(DirstateItem::new_as_pyobject(py, entry)?))
             },
             None => Ok(default)
         }
@@ -450,7 +450,7 @@
             .map_err(|e| v2_error(py, e))?
         {
             Some(entry) => {
-                Ok(make_dirstate_item(py, &entry)?)
+                Ok(DirstateItem::new_as_pyobject(py, entry)?)
             },
             None => Err(PyErr::new::<exc::KeyError, _>(
                 py,
@@ -639,7 +639,7 @@
         let (f, entry) = res.map_err(|e| v2_error(py, e))?;
         Ok(Some((
             PyBytes::new(py, f.as_bytes()),
-            make_dirstate_item(py, &entry)?,
+            DirstateItem::new_as_pyobject(py, entry)?,
         )))
     }
 }