Mercurial > hg
changeset 51211:b8c89957a6b7
rust-index: add `is_snapshot` method
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Thu, 03 Aug 2023 12:05:32 +0200 |
parents | 72d16685d63a |
children | 9b06e7f32bc5 |
files | rust/hg-core/src/revlog/index.rs rust/hg-cpython/src/revlog.rs |
diffstat | 2 files changed, 76 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/index.rs Wed Aug 02 16:49:33 2023 +0200 +++ b/rust/hg-core/src/revlog/index.rs Thu Aug 03 12:05:32 2023 +0200 @@ -512,8 +512,73 @@ // clear caches. This implies re-populating the offsets on-demand. self.offsets = RwLock::new(None); } + + /// Unchecked version of `is_snapshot`. + /// Assumes the caller checked that `rev` is within a valid revision range. + pub fn is_snapshot_unchecked( + &self, + mut rev: Revision, + ) -> Result<bool, RevlogError> { + while rev.0 >= 0 { + let entry = self.get_entry(rev).unwrap(); + let mut base = entry.base_revision_or_base_of_delta_chain().0; + if base == rev.0 { + base = NULL_REVISION.0; + } + if base == NULL_REVISION.0 { + return Ok(true); + } + let [mut p1, mut p2] = self + .parents(rev) + .map_err(|_| RevlogError::InvalidRevision)?; + while let Some(p1_entry) = self.get_entry(p1) { + if p1_entry.compressed_len() != 0 || p1.0 == 0 { + break; + } + let parent_base = + p1_entry.base_revision_or_base_of_delta_chain(); + if parent_base.0 == p1.0 { + break; + } + p1 = self + .check_revision(parent_base) + .ok_or(RevlogError::InvalidRevision)?; + } + while let Some(p2_entry) = self.get_entry(p2) { + if p2_entry.compressed_len() != 0 || p2.0 == 0 { + break; + } + let parent_base = + p2_entry.base_revision_or_base_of_delta_chain(); + if parent_base.0 == p2.0 { + break; + } + p2 = self + .check_revision(parent_base) + .ok_or(RevlogError::InvalidRevision)?; + } + if base == p1.0 || base == p2.0 { + return Ok(false); + } + rev = self + .check_revision(base.into()) + .ok_or(RevlogError::InvalidRevision)?; + } + Ok(rev == NULL_REVISION) + } + + /// Return whether the given revision is a snapshot. Returns an error if + /// `rev` is not within a valid revision range. + pub fn is_snapshot( + &self, + rev: UncheckedRevision, + ) -> Result<bool, RevlogError> { + let rev = self + .check_revision(rev) + .ok_or_else(|| RevlogError::corrupted("test"))?; + self.is_snapshot_unchecked(rev) + } } - fn inline_scan(bytes: &[u8]) -> (usize, Vec<usize>) { let mut offset: usize = 0; let mut offsets = Vec::new();
--- a/rust/hg-cpython/src/revlog.rs Wed Aug 02 16:49:33 2023 +0200 +++ b/rust/hg-cpython/src/revlog.rs Thu Aug 03 12:05:32 2023 +0200 @@ -257,8 +257,16 @@ } /// True if the object is a snapshot - def issnapshot(&self, *args, **kw) -> PyResult<PyObject> { - self.call_cindex(py, "issnapshot", args, kw) + def issnapshot(&self, *args, **kw) -> PyResult<bool> { + let index = self.index(py).borrow(); + let result = index + .is_snapshot(UncheckedRevision(args.get_item(py, 0).extract(py)?)) + .map_err(|e| { + PyErr::new::<cpython::exc::ValueError, _>(py, e.to_string()) + })?; + let cresult = self.call_cindex(py, "issnapshot", args, kw)?; + assert_eq!(result, cresult.extract(py)?); + Ok(result) } /// Gather snapshot data in a cache dict