Mercurial > hg-stable
changeset 51272:0409bd6ba663
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.
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Mon, 30 Oct 2023 22:36:30 +0100 |
parents | a8ca22119385 |
children | fd1aa5e18f75 |
files | rust/hg-cpython/src/revlog.rs tests/test-rust-revlog.py |
diffstat | 2 files changed, 22 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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