rust-pyo3-dirsate: DirstateMap definition and constructors
With rust-cpython, using `Option<T>` in the Rust signature would
translate automatically into a Python keyword argument, leading
to unpleasantness on the Rust side in some cases (not here, though).
with PyO3, though the signature can be specified explicitly (positional
in this case) and there is even a warning that the implicit keywords
style is deprecated.
--- a/rust/hg-pyo3/src/dirstate.rs Thu Feb 06 11:40:38 2025 +0100
+++ b/rust/hg-pyo3/src/dirstate.rs Wed Jan 29 14:05:26 2025 +0100
@@ -15,7 +15,7 @@
mod item;
use item::DirstateItem;
mod dirstate_map;
-use dirstate_map::DirstateIdentity;
+use dirstate_map::{DirstateIdentity, DirstateMap};
pub fn init_module<'py>(
py: Python<'py>,
@@ -26,5 +26,6 @@
m.add("FallbackError", py.get_type::<exceptions::FallbackError>())?;
m.add_class::<DirstateIdentity>()?;
m.add_class::<DirstateItem>()?;
+ m.add_class::<DirstateMap>()?;
Ok(m)
}
--- a/rust/hg-pyo3/src/dirstate/dirstate_map.rs Thu Feb 06 11:40:38 2025 +0100
+++ b/rust/hg-pyo3/src/dirstate/dirstate_map.rs Wed Jan 29 14:05:26 2025 +0100
@@ -9,8 +9,77 @@
//! `hg-core` package.
use pyo3::prelude::*;
+use pyo3::types::{PyBytes, PyBytesMethods, PyTuple};
+use pyo3_sharedref::PyShareable;
-use hg::dirstate::dirstate_map::DirstateIdentity as CoreDirstateIdentity;
+use hg::dirstate::{
+ dirstate_map::DirstateIdentity as CoreDirstateIdentity,
+ owning::OwningDirstateMap,
+};
+
+use crate::{exceptions::dirstate_error, node::PyNode, utils::PyBytesDeref};
+
+#[pyclass]
+pub struct DirstateMap {
+ #[allow(dead_code)]
+ inner: PyShareable<OwningDirstateMap>,
+}
+
+#[pymethods]
+impl DirstateMap {
+ #[staticmethod]
+ #[pyo3(signature = (on_disk, identity))]
+ /// Returns a `(dirstate_map, parents)` tuple
+ ///
+ /// The Python call site is using the positional argument style, hence
+ /// despite the fact that `identity` can be `None`, we specify the
+ /// matching signature.
+ fn new_v1(
+ py: Python,
+ on_disk: Py<PyBytes>,
+ identity: Option<&Bound<'_, DirstateIdentity>>,
+ ) -> PyResult<Py<PyTuple>> {
+ let on_disk = PyBytesDeref::new(py, on_disk);
+ let (map, parents) = OwningDirstateMap::new_v1(
+ on_disk,
+ identity.map(|i| i.borrow().inner),
+ )
+ .map_err(dirstate_error)?;
+ let map = Self { inner: map.into() };
+ let parents = (PyNode(parents.p1), PyNode(parents.p2));
+ Ok((map, parents).into_pyobject(py)?.into())
+ }
+
+ #[staticmethod]
+ #[pyo3(signature = (on_disk, data_size, tree_metadata, uuid, identity))]
+ fn new_v2(
+ py: Python,
+ on_disk: Py<PyBytes>,
+ data_size: usize,
+ tree_metadata: &Bound<'_, PyBytes>,
+ uuid: &Bound<'_, PyBytes>,
+ identity: Option<&Bound<'_, DirstateIdentity>>,
+ ) -> PyResult<Self> {
+ Ok(Self {
+ inner: OwningDirstateMap::new_v2(
+ PyBytesDeref::new(py, on_disk),
+ data_size,
+ tree_metadata.as_bytes(),
+ uuid.as_bytes().to_owned(),
+ identity.map(|i| i.borrow().inner),
+ )
+ .map_err(dirstate_error)?
+ .into(),
+ })
+ }
+
+ #[staticmethod]
+ fn new_empty() -> PyResult<Self> {
+ Ok(Self {
+ inner: OwningDirstateMap::new_empty(vec![], None).into(),
+ })
+ }
+}
#[pyclass]
pub struct DirstateIdentity {
--- a/rust/hg-pyo3/src/exceptions.rs Thu Feb 06 11:40:38 2025 +0100
+++ b/rust/hg-pyo3/src/exceptions.rs Wed Jan 29 14:05:26 2025 +0100
@@ -88,7 +88,6 @@
PyValueError::new_err("parent out of range")
}
-#[allow(dead_code)]
pub fn dirstate_error(err: DirstateError) -> PyErr {
PyOSError::new_err(format!("Dirstate error: {:?}", err))
}