comparison rust/hg-core/src/ancestors.rs @ 41246:619ee4039bd4

rust: MissingAncestors.basesheads() This new API method on `MissingAncestors` leverages directly the Rust implementation for relative heads of a set, and also lowers the cost of returning the results to Python in the context of discovery. These interchange costs can probably be further reduced by implementing the `partialdiscovery` class in Rust, but that will be investigated in the 5.0 development cycle. Differential Revision: https://phab.mercurial-scm.org/D5584
author Georges Racinet <georges.racinet@octobus.net>
date Mon, 14 Jan 2019 17:07:39 +0100
parents 168041fa6d5f
children 70827ebba453
comparison
equal deleted inserted replaced
41245:2a8782cc2e16 41246:619ee4039bd4
8 //! Rust versions of generic DAG ancestors algorithms for Mercurial 8 //! Rust versions of generic DAG ancestors algorithms for Mercurial
9 9
10 use super::{Graph, GraphError, Revision, NULL_REVISION}; 10 use super::{Graph, GraphError, Revision, NULL_REVISION};
11 use std::cmp::max; 11 use std::cmp::max;
12 use std::collections::{BinaryHeap, HashSet}; 12 use std::collections::{BinaryHeap, HashSet};
13 use crate::dagops;
13 14
14 /// Iterator over the ancestors of a given list of revisions 15 /// Iterator over the ancestors of a given list of revisions
15 /// This is a generic type, defined and implemented for any Graph, so that 16 /// This is a generic type, defined and implemented for any Graph, so that
16 /// it's easy to 17 /// it's easy to
17 /// 18 ///
225 /// 226 ///
226 /// This is useful in unit tests, but also setdiscovery.py does 227 /// This is useful in unit tests, but also setdiscovery.py does
227 /// read the bases attribute of a ancestor.missingancestors instance. 228 /// read the bases attribute of a ancestor.missingancestors instance.
228 pub fn get_bases<'a>(&'a self) -> &'a HashSet<Revision> { 229 pub fn get_bases<'a>(&'a self) -> &'a HashSet<Revision> {
229 &self.bases 230 &self.bases
231 }
232
233 /// Computes the relative heads of current bases.
234 ///
235 /// The object is still usable after this.
236 pub fn bases_heads(&self) -> Result<HashSet<Revision>, GraphError> {
237 dagops::heads(&self.graph, self.bases.iter())
238 }
239
240 /// Consumes the object and returns the relative heads of its bases.
241 pub fn into_bases_heads(mut self) -> Result<HashSet<Revision>, GraphError> {
242 dagops::retain_heads(&self.graph, &mut self.bases)?;
243 Ok(self.bases)
230 } 244 }
231 245
232 pub fn add_bases( 246 pub fn add_bases(
233 &mut self, 247 &mut self,
234 new_bases: impl IntoIterator<Item = Revision>, 248 new_bases: impl IntoIterator<Item = Revision>,
554 let revs: Vec<Revision> = lazy.iter().map(|r| r.unwrap()).collect(); 568 let revs: Vec<Revision> = lazy.iter().map(|r| r.unwrap()).collect();
555 assert_eq!(revs, vec![8, 7, 4, 3, 2, 1, 0]); 569 assert_eq!(revs, vec![8, 7, 4, 3, 2, 1, 0]);
556 } 570 }
557 571
558 #[test] 572 #[test]
559 /// Test constructor, add/get bases 573 /// Test constructor, add/get bases and heads
560 fn test_missing_bases() { 574 fn test_missing_bases() -> Result<(), GraphError> {
561 let mut missing_ancestors = 575 let mut missing_ancestors =
562 MissingAncestors::new(SampleGraph, [5, 3, 1, 3].iter().cloned()); 576 MissingAncestors::new(SampleGraph, [5, 3, 1, 3].iter().cloned());
563 let mut as_vec: Vec<Revision> = 577 let mut as_vec: Vec<Revision> =
564 missing_ancestors.get_bases().iter().cloned().collect(); 578 missing_ancestors.get_bases().iter().cloned().collect();
565 as_vec.sort(); 579 as_vec.sort();
567 581
568 missing_ancestors.add_bases([3, 7, 8].iter().cloned()); 582 missing_ancestors.add_bases([3, 7, 8].iter().cloned());
569 as_vec = missing_ancestors.get_bases().iter().cloned().collect(); 583 as_vec = missing_ancestors.get_bases().iter().cloned().collect();
570 as_vec.sort(); 584 as_vec.sort();
571 assert_eq!(as_vec, [1, 3, 5, 7, 8]); 585 assert_eq!(as_vec, [1, 3, 5, 7, 8]);
586
587 as_vec = missing_ancestors.bases_heads()?.iter().cloned().collect();
588 as_vec.sort();
589 assert_eq!(as_vec, [3, 5, 7, 8]);
590 Ok(())
572 } 591 }
573 592
574 fn assert_missing_remove( 593 fn assert_missing_remove(
575 bases: &[Revision], 594 bases: &[Revision],
576 revs: &[Revision], 595 revs: &[Revision],