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