diff 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
line wrap: on
line diff
--- a/rust/hg-core/src/ancestors.rs	Mon Jan 14 18:52:01 2019 +0100
+++ b/rust/hg-core/src/ancestors.rs	Mon Jan 14 17:07:39 2019 +0100
@@ -10,6 +10,7 @@
 use super::{Graph, GraphError, Revision, NULL_REVISION};
 use std::cmp::max;
 use std::collections::{BinaryHeap, HashSet};
+use crate::dagops;
 
 /// Iterator over the ancestors of a given list of revisions
 /// This is a generic type, defined and implemented for any Graph, so that
@@ -229,6 +230,19 @@
         &self.bases
     }
 
+    /// Computes the relative heads of current bases.
+    ///
+    /// The object is still usable after this.
+    pub fn bases_heads(&self) -> Result<HashSet<Revision>, GraphError> {
+        dagops::heads(&self.graph, self.bases.iter())
+    }
+
+    /// Consumes the object and returns the relative heads of its bases.
+    pub fn into_bases_heads(mut self) -> Result<HashSet<Revision>, GraphError> {
+        dagops::retain_heads(&self.graph, &mut self.bases)?;
+        Ok(self.bases)
+    }
+
     pub fn add_bases(
         &mut self,
         new_bases: impl IntoIterator<Item = Revision>,
@@ -556,8 +570,8 @@
     }
 
     #[test]
-    /// Test constructor, add/get bases
-    fn test_missing_bases() {
+    /// Test constructor, add/get bases and heads
+    fn test_missing_bases() -> Result<(), GraphError> {
         let mut missing_ancestors =
             MissingAncestors::new(SampleGraph, [5, 3, 1, 3].iter().cloned());
         let mut as_vec: Vec<Revision> =
@@ -569,6 +583,11 @@
         as_vec = missing_ancestors.get_bases().iter().cloned().collect();
         as_vec.sort();
         assert_eq!(as_vec, [1, 3, 5, 7, 8]);
+
+        as_vec = missing_ancestors.bases_heads()?.iter().cloned().collect();
+        as_vec.sort();
+        assert_eq!(as_vec, [3, 5, 7, 8]);
+        Ok(())
     }
 
     fn assert_missing_remove(