552 /// Python-specific shortcut to save on PyList creation |
552 /// Python-specific shortcut to save on PyList creation |
553 pub fn head_revs_shortcut( |
553 pub fn head_revs_shortcut( |
554 &self, |
554 &self, |
555 ) -> Result<Option<Vec<Revision>>, GraphError> { |
555 ) -> Result<Option<Vec<Revision>>, GraphError> { |
556 self.head_revs_filtered(&HashSet::new(), true) |
556 self.head_revs_filtered(&HashSet::new(), true) |
|
557 } |
|
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)) |
557 } |
608 } |
558 |
609 |
559 /// Return the head revisions of this index |
610 /// Return the head revisions of this index |
560 pub fn head_revs_filtered( |
611 pub fn head_revs_filtered( |
561 &self, |
612 &self, |