changeset 52844:9e6b50837b37

rust-pyo3-revlog: _revisioncache
author Rapha?l Gom?s <rgomes@octobus.net>
date Fri, 03 Jan 2025 15:45:06 +0100
parents dd3a2948804f
children c72d8df0c080
files rust/hg-pyo3/src/revlog/mod.rs
diffstat 1 files changed, 57 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-pyo3/src/revlog/mod.rs	Fri Jan 03 15:44:29 2025 +0100
+++ b/rust/hg-pyo3/src/revlog/mod.rs	Fri Jan 03 15:45:06 2025 +0100
@@ -41,6 +41,7 @@
     BaseRevision, Revision, UncheckedRevision, NULL_REVISION,
 };
 
+use crate::util::PyBytesDeref;
 use crate::{
     exceptions::{
         graph_error, map_lock_error, map_try_lock_error, nodemap_error,
@@ -302,6 +303,62 @@
     }
 
     #[getter]
+    fn _revisioncache(&self, py: Python<'_>) -> PyResult<PyObject> {
+        match &self.revision_cache {
+            None => Ok(py.None()),
+            Some(cache) => Ok(cache.clone_ref(py)),
+        }
+    }
+
+    #[setter]
+    fn set__revisioncache(
+        slf: &Bound<'_, Self>,
+        py: Python<'_>,
+        value: Option<PyObject>,
+    ) -> PyResult<()> {
+        let mut self_ref = slf.borrow_mut();
+        self_ref.revision_cache = value.as_ref().map(|v| v.clone_ref(py));
+
+        match value {
+            None => {
+                // This means the property has been deleted, *not* that the
+                // property has been set to `None`. Whatever happens is up
+                // to the implementation. Here we just set it to `None`.
+                self_ref.revision_cache.take();
+            }
+            Some(tuple) => {
+                if tuple.is_none(py) {
+                    self_ref.revision_cache.take();
+                    return Ok(());
+                }
+                drop(self_ref);
+                let tuple: &Bound<'_, PyTuple> = tuple.downcast_bound(py)?;
+                let node = tuple.get_item(0)?;
+                let node = node_from_py_bytes(node.downcast()?)?;
+                let rev: BaseRevision = tuple.get_item(1)?.extract()?;
+                // Ok because Python only sets this if the revision has been
+                // checked
+                let rev = Revision(rev);
+                let data = tuple.get_item(2)?;
+                let bytes = data.downcast_into::<PyBytes>()?.unbind();
+                Self::with_core_read(slf, |_self_ref, irl| {
+                    let mut last_revision_cache = irl
+                        .last_revision_cache
+                        .lock()
+                        .expect("lock should not be held");
+                    *last_revision_cache = Some((
+                        node,
+                        rev,
+                        Box::new(PyBytesDeref::new(py, bytes)),
+                    ));
+                    Ok(())
+                })?;
+            }
+        }
+        Ok(())
+    }
+
+    #[getter]
     fn index_file(
         slf: &Bound<'_, Self>,
         py: Python<'_>,