comparison rust/hg-cpython/src/revlog.rs @ 51225:89ce6a49bfeb

rust-index: implement common_ancestors_heads() and ancestors() The only differences betwwen `common_ancestors_heads()` and `find_gca_candidates()` seems to be that: - the former accepts "overlapping" input revisions (meaning with duplicates). - limitation to 24 inputs (in the C code), that we translate to using the arbitrary size bit sets in the Rust code because we cannot bail to Python. Given that the input is expected to be small in most cases, we take the heavy handed approach of going through a HashSet and wait for perfomance assessment In case this is used via `hg-cpython`, we can anyway absorb the overhead by having `commonancestorheads` build a vector of unique values directly, and introduce a thin wrapper over `find_gca_candidates`, to take care of bit set type dispatching only. As far as `ancestors` is concerneed, this is just chaining `common_ancestors_heads()` with `find_deepest_revs`.
author Georges Racinet <georges.racinet@octobus.net>
date Wed, 18 Oct 2023 15:35:38 +0200
parents fc05dd74e907
children 1b23aaf5eb7b
comparison
equal deleted inserted replaced
51224:43241f31cf5b 51225:89ce6a49bfeb
194 194
195 // index_methods (tp_methods). Same ordering as in revlog.c 195 // index_methods (tp_methods). Same ordering as in revlog.c
196 196
197 /// return the gca set of the given revs 197 /// return the gca set of the given revs
198 def ancestors(&self, *args, **kw) -> PyResult<PyObject> { 198 def ancestors(&self, *args, **kw) -> PyResult<PyObject> {
199 self.call_cindex(py, "ancestors", args, kw) 199 let rust_res = self.inner_ancestors(py, args)?;
200
201 let c_res = self.call_cindex(py, "ancestors", args, kw)?;
202 // the algorithm should always provide the results in reverse ordering
203 assert_py_eq(py, "ancestors", &rust_res, &c_res)?;
204
205 Ok(rust_res)
200 } 206 }
201 207
202 /// return the heads of the common ancestors of the given revs 208 /// return the heads of the common ancestors of the given revs
203 def commonancestorsheads(&self, *args, **kw) -> PyResult<PyObject> { 209 def commonancestorsheads(&self, *args, **kw) -> PyResult<PyObject> {
204 self.call_cindex(py, "commonancestorsheads", args, kw) 210 let rust_res = self.inner_commonancestorsheads(py, args)?;
211
212 let c_res = self.call_cindex(py, "commonancestorsheads", args, kw)?;
213 // the algorithm should always provide the results in reverse ordering
214 assert_py_eq(py, "commonancestorsheads", &rust_res, &c_res)?;
215
216 Ok(rust_res)
205 } 217 }
206 218
207 /// Clear the index caches and inner py_class data. 219 /// Clear the index caches and inner py_class data.
208 /// It is Python's responsibility to call `update_nodemap_data` again. 220 /// It is Python's responsibility to call `update_nodemap_data` again.
209 def clearcaches(&self, *args, **kw) -> PyResult<PyObject> { 221 def clearcaches(&self, *args, **kw) -> PyResult<PyObject> {
848 .map(|r| PyRevision::from(*r).into_py_object(py).into_object()) 860 .map(|r| PyRevision::from(*r).into_py_object(py).into_object())
849 .collect(); 861 .collect();
850 Ok(PyList::new(py, &as_vec).into_object()) 862 Ok(PyList::new(py, &as_vec).into_object())
851 } 863 }
852 864
865 fn inner_ancestors(
866 &self,
867 py: Python,
868 py_revs: &PyTuple,
869 ) -> PyResult<PyObject> {
870 let index = &mut *self.index(py).borrow_mut();
871 let revs: Vec<_> = rev_pyiter_collect(py, py_revs.as_object(), index)?;
872 let as_vec: Vec<_> = index
873 .ancestors(&revs)
874 .map_err(|e| graph_error(py, e))?
875 .iter()
876 .map(|r| PyRevision::from(*r).into_py_object(py).into_object())
877 .collect();
878 Ok(PyList::new(py, &as_vec).into_object())
879 }
880
881 fn inner_commonancestorsheads(
882 &self,
883 py: Python,
884 py_revs: &PyTuple,
885 ) -> PyResult<PyObject> {
886 let index = &mut *self.index(py).borrow_mut();
887 let revs: Vec<_> = rev_pyiter_collect(py, py_revs.as_object(), index)?;
888 let as_vec: Vec<_> = index
889 .common_ancestor_heads(&revs)
890 .map_err(|e| graph_error(py, e))?
891 .iter()
892 .map(|r| PyRevision::from(*r).into_py_object(py).into_object())
893 .collect();
894 Ok(PyList::new(py, &as_vec).into_object())
895 }
896
853 fn inner_computephasesmapsets( 897 fn inner_computephasesmapsets(
854 &self, 898 &self,
855 py: Python, 899 py: Python,
856 py_roots: PyDict, 900 py_roots: PyDict,
857 ) -> PyResult<PyObject> { 901 ) -> PyResult<PyObject> {