diff --git a/rust/hg-core/src/revlog/index.rs b/rust/hg-core/src/revlog/index.rs index 61a6ef876efde761ecdfa416f3e6c81a33cc10d8_cnVzdC9oZy1jb3JlL3NyYy9yZXZsb2cvaW5kZXgucnM=..1b23aaf5eb7b5169bbbdf95b4a0ad7214ab66a82_cnVzdC9oZy1jb3JlL3NyYy9yZXZsb2cvaW5kZXgucnM= 100644 --- a/rust/hg-core/src/revlog/index.rs +++ b/rust/hg-core/src/revlog/index.rs @@ -1053,7 +1053,9 @@ let revisions: Vec<Revision> = as_set.into_iter().collect(); - if revisions.len() <= 63 { + if revisions.len() < 8 { + self.find_gca_candidates::<u8>(&revisions) + } else if revisions.len() < 64 { self.find_gca_candidates::<u64>(&revisions) } else { self.find_gca_candidates::<NonStaticPoisonableBitSet>(&revisions) @@ -1314,6 +1316,7 @@ } const U64_POISON: u64 = 1 << 63; +const U8_POISON: u8 = 1 << 7; impl PoisonableBitSet for u64 { fn vec_of_empty(_sets_size: usize, vec_len: usize) -> Vec<Self> { @@ -1361,6 +1364,52 @@ } } +impl PoisonableBitSet for u8 { + fn vec_of_empty(_sets_size: usize, vec_len: usize) -> Vec<Self> { + vec![0; vec_len] + } + + fn size(&self) -> usize { + 1 + } + + fn capacity(&self) -> usize { + 7 + } + + fn add(&mut self, n: usize) { + (*self) |= 1 << n; + } + + fn discard(&mut self, n: usize) { + (*self) &= u8::MAX - (1 << n); + } + + fn union(&mut self, other: &Self) { + if *self != *other { + (*self) |= *other; + } + } + + fn is_full_range(&self, n: usize) -> bool { + *self + 1 == (1 << n) + } + + fn is_empty(&self) -> bool { + *self == 0 + } + + fn poison(&mut self) { + *self = U8_POISON; + } + + fn is_poisoned(&self) -> bool { + // equality comparison would be tempting but would not resist + // operations after poisoning (even if these should be bogus). + *self >= U8_POISON + } +} + /// A poisonable bit set whose capacity is not known at compile time but /// is constant after initial construction /// diff --git a/rust/hg-cpython/src/revlog.rs b/rust/hg-cpython/src/revlog.rs index 61a6ef876efde761ecdfa416f3e6c81a33cc10d8_cnVzdC9oZy1jcHl0aG9uL3NyYy9yZXZsb2cucnM=..1b23aaf5eb7b5169bbbdf95b4a0ad7214ab66a82_cnVzdC9oZy1jcHl0aG9uL3NyYy9yZXZsb2cucnM= 100644 --- a/rust/hg-cpython/src/revlog.rs +++ b/rust/hg-cpython/src/revlog.rs @@ -20,7 +20,10 @@ }; use hg::{ errors::HgError, - index::{IndexHeader, Phase, RevisionDataParams, SnapshotsCache}, + index::{ + IndexHeader, Phase, RevisionDataParams, SnapshotsCache, + INDEX_ENTRY_SIZE, + }, nodemap::{Block, NodeMapError, NodeTree}, revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex}, BaseRevision, Revision, UncheckedRevision, NULL_REVISION, @@ -483,8 +486,14 @@ @property def entry_size(&self) -> PyResult<PyInt> { - self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::<PyInt>(py) + let rust_res: PyInt = INDEX_ENTRY_SIZE.to_py_object(py); + + let c_res = self.cindex(py).borrow().inner() + .getattr(py, "entry_size")?; + assert_py_eq(py, "entry_size", rust_res.as_object(), &c_res)?; + + Ok(rust_res) } @property def rust_ext_compat(&self) -> PyResult<PyInt> { @@ -487,8 +496,16 @@ } @property def rust_ext_compat(&self) -> PyResult<PyInt> { - self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py) + // will be entirely removed when the Rust index yet useful to + // implement in Rust to detangle things when removing `self.cindex` + let rust_res: PyInt = 1.to_py_object(py); + + let c_res = self.cindex(py).borrow().inner() + .getattr(py, "rust_ext_compat")?; + assert_py_eq(py, "rust_ext_compat", rust_res.as_object(), &c_res)?; + + Ok(rust_res) } }); @@ -671,7 +688,7 @@ let rust_index_len = self.index(py).borrow().len(); let cindex_len = self.cindex(py).borrow().inner().len(py)?; assert_eq!(rust_index_len, cindex_len); - Ok(cindex_len) + Ok(rust_index_len) } /// This is scaffolding at this point, but it could also become