##// END OF EJS Templates
revlog: add a Rust implementation of `headrevsdiff`...
Arseniy Alekseyev -
r52290:b01e7d97 default
parent child Browse files
Show More
@@ -556,6 +556,57 b' impl Index {'
556 556 self.head_revs_filtered(&HashSet::new(), true)
557 557 }
558 558
559 /// Return the heads removed and added by advancing from `begin` to `end`.
560 /// In revset language, we compute:
561 /// - `heads(:begin)-heads(:end)`
562 /// - `heads(:end)-heads(:begin)`
563 pub fn head_revs_diff(
564 &self,
565 begin: Revision,
566 end: Revision,
567 ) -> Result<(Vec<Revision>, Vec<Revision>), GraphError> {
568 let mut heads_added = vec![];
569 let mut heads_removed = vec![];
570
571 let mut acc = HashSet::new();
572 let Revision(begin) = begin;
573 let Revision(end) = end;
574 let mut i = end;
575
576 while i > begin {
577 // acc invariant:
578 // `j` is in the set iff `j <= i` and it has children
579 // among `i+1..end` (inclusive)
580 if !acc.remove(&i) {
581 heads_added.push(Revision(i));
582 }
583 for Revision(parent) in self.parents(Revision(i))? {
584 acc.insert(parent);
585 }
586 i -= 1;
587 }
588
589 // At this point `acc` contains old revisions that gained new children.
590 // We need to check if they had any children before. If not, those
591 // revisions are the removed heads.
592 while !acc.is_empty() {
593 // acc invariant:
594 // `j` is in the set iff `j <= i` and it has children
595 // among `begin+1..end`, but not among `i+1..begin` (inclusive)
596
597 assert!(i >= -1); // yes, `-1` can also be a head if the repo is empty
598 if acc.remove(&i) {
599 heads_removed.push(Revision(i));
600 }
601 for Revision(parent) in self.parents(Revision(i))? {
602 acc.remove(&parent);
603 }
604 i -= 1;
605 }
606
607 Ok((heads_removed, heads_added))
608 }
609
559 610 /// Return the head revisions of this index
560 611 pub fn head_revs_filtered(
561 612 &self,
@@ -315,6 +315,15 b' py_class!(pub class Index |py| {'
315 315 Ok(rust_res)
316 316 }
317 317
318 /// get diff in head revisions
319 def headrevsdiff(&self, *args, **_kw) -> PyResult<PyObject> {
320 let rust_res = self.inner_headrevsdiff(
321 py,
322 &args.get_item(py, 0),
323 &args.get_item(py, 1))?;
324 Ok(rust_res)
325 }
326
318 327 /// get filtered head revisions
319 328 def headrevsfiltered(&self, *args, **_kw) -> PyResult<PyObject> {
320 329 let rust_res = self.inner_headrevsfiltered(py, &args.get_item(py, 0))?;
@@ -827,6 +836,38 b' impl Index {'
827 836 .into_object())
828 837 }
829 838
839 fn check_revision(
840 index: &hg::index::Index,
841 rev: UncheckedRevision,
842 py: Python,
843 ) -> PyResult<Revision> {
844 index
845 .check_revision(rev)
846 .ok_or_else(|| rev_not_in_index(py, rev))
847 }
848
849 fn inner_headrevsdiff(
850 &self,
851 py: Python,
852 begin: &PyObject,
853 end: &PyObject,
854 ) -> PyResult<PyObject> {
855 let begin = begin.extract::<BaseRevision>(py)?;
856 let end = end.extract::<BaseRevision>(py)?;
857 let index = &mut *self.index(py).borrow_mut();
858 let begin =
859 Self::check_revision(index, UncheckedRevision(begin - 1), py)?;
860 let end = Self::check_revision(index, UncheckedRevision(end - 1), py)?;
861 let (removed, added) = index
862 .head_revs_diff(begin, end)
863 .map_err(|e| graph_error(py, e))?;
864 let removed: Vec<_> =
865 removed.into_iter().map(PyRevision::from).collect();
866 let added: Vec<_> = added.into_iter().map(PyRevision::from).collect();
867 let res = (removed, added).to_py_object(py).into_object();
868 Ok(res)
869 }
870
830 871 fn inner_headrevsfiltered(
831 872 &self,
832 873 py: Python,
General Comments 0
You need to be logged in to leave comments. Login now