rust-revlog: add invalidation detection to `NodeTree` class
This will be useful for callers, such as `scmutil` who reuse a
`NodeTree` instance as a cache. They would otherwise get hard
errors if any mutation of the index occurred since instantiation.
This is something the C index does not provide.
--- a/rust/hg-cpython/src/revlog.rs Thu Nov 02 15:50:13 2023 +0100
+++ b/rust/hg-cpython/src/revlog.rs Mon Oct 30 22:36:30 2023 +0100
@@ -979,6 +979,24 @@
Self::create_instance(py, RefCell::new(nt), RefCell::new(index))
}
+ /// Tell whether the NodeTree is still valid
+ ///
+ /// In case of mutation of the index, the given results are not
+ /// guaranteed to be correct, and in fact, the methods borrowing
+ /// the inner index would fail because of `PySharedRef` poisoning
+ /// (generation-based guard), same as iterating on a `dict` that has
+ /// been meanwhile mutated.
+ def is_invalidated(&self) -> PyResult<bool> {
+ let leaked = self.index(py).borrow();
+ let result = unsafe { leaked.try_borrow(py) };
+ // two cases for result to be an error:
+ // - the index has previously been mutably borrowed
+ // - there is currently a mutable borrow
+ // in both cases this amounts for previous results related to
+ // the index to still be valid.
+ Ok(result.is_err())
+ }
+
def insert(&self, rev: PyRevision) -> PyResult<PyObject> {
let leaked = self.index(py).borrow();
let index = &*unsafe { leaked.try_borrow(py)? };
--- a/tests/test-rust-revlog.py Thu Nov 02 15:50:13 2023 +0100
+++ b/tests/test-rust-revlog.py Mon Oct 30 22:36:30 2023 +0100
@@ -87,6 +87,10 @@
self.assertEqual(shortest, expected)
self.assertEqual(nt.prefix_rev_lookup(hex_node[:shortest]), i)
+ # test invalidation (generation poisoning) detection
+ del idx[3]
+ self.assertTrue(nt.is_invalidated())
+
if __name__ == '__main__':
import silenttestrunner