##// END OF EJS Templates
rust-index: implement common_ancestors_heads() and ancestors()...
Georges Racinet -
r52118:89ce6a49 default
parent child Browse files
Show More
@@ -1036,14 +1036,40 b' impl Index {'
1036
1036
1037 /// Given a (possibly overlapping) set of revs, return all the
1037 /// Given a (possibly overlapping) set of revs, return all the
1038 /// common ancestors heads: `heads(::args[0] and ::a[1] and ...)`
1038 /// common ancestors heads: `heads(::args[0] and ::a[1] and ...)`
1039 pub fn common_ancestor_heads(&self, _revisions: &[Revision]) {
1039 pub fn common_ancestor_heads(
1040 todo!()
1040 &self,
1041 revisions: &[Revision],
1042 ) -> Result<Vec<Revision>, GraphError> {
1043 // given that revisions is expected to be small, we find this shortcut
1044 // potentially acceptable, especially given that `hg-cpython` could
1045 // very much bypass this, constructing a vector of unique values from
1046 // the onset.
1047 let as_set: HashSet<Revision> = revisions.iter().copied().collect();
1048 // Besides deduplicating, the C version also implements the shortcut
1049 // for `NULL_REVISION`:
1050 if as_set.contains(&NULL_REVISION) {
1051 return Ok(vec![]);
1052 }
1053
1054 let revisions: Vec<Revision> = as_set.into_iter().collect();
1055
1056 if revisions.len() <= 63 {
1057 self.find_gca_candidates::<u64>(&revisions)
1058 } else {
1059 self.find_gca_candidates::<NonStaticPoisonableBitSet>(&revisions)
1060 }
1061 }
1062
1063 pub fn ancestors(
1064 &self,
1065 revisions: &[Revision],
1066 ) -> Result<Vec<Revision>, GraphError> {
1067 self.find_deepest_revs(&self.common_ancestor_heads(revisions)?)
1041 }
1068 }
1042
1069
1043 /// Given a disjoint set of revs, return all candidates for the
1070 /// Given a disjoint set of revs, return all candidates for the
1044 /// greatest common ancestor. In revset notation, this is the set
1071 /// greatest common ancestor. In revset notation, this is the set
1045 /// `heads(::a and ::b and ...)`
1072 /// `heads(::a and ::b and ...)`
1046 #[allow(dead_code)]
1047 fn find_gca_candidates<BS: PoisonableBitSet + Clone>(
1073 fn find_gca_candidates<BS: PoisonableBitSet + Clone>(
1048 &self,
1074 &self,
1049 revs: &[Revision],
1075 revs: &[Revision],
@@ -1147,7 +1173,6 b' impl Index {'
1147
1173
1148 /// Given a disjoint set of revs, return the subset with the longest path
1174 /// Given a disjoint set of revs, return the subset with the longest path
1149 /// to the root.
1175 /// to the root.
1150 #[allow(dead_code)]
1151 fn find_deepest_revs(
1176 fn find_deepest_revs(
1152 &self,
1177 &self,
1153 revs: &[Revision],
1178 revs: &[Revision],
@@ -196,12 +196,24 b' py_class!(pub class MixedIndex |py| {'
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.
@@ -850,6 +862,38 b' impl MixedIndex {'
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,
General Comments 0
You need to be logged in to leave comments. Login now