mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
dag: add DagAlgorithm.first_ancestors
Summary: This will be useful to optimize `_firstancestors` revset, which is useful to calculate a linear branch to draw growth graphs. Without a fast path, the pure Python `_firstancestors` implementation would have id <-> name translation overhead that makes Rust changelog O(20) slower than the Python revlog. Reviewed By: sfilipco Differential Revision: D26182240 fbshipit-source-id: d44f5ca5dc8c38df74281832931d87868791209e
This commit is contained in:
parent
01b0122b0b
commit
fb187ef86e
@ -203,6 +203,32 @@ pub(crate) async fn first_ancestor_nth(
|
|||||||
Ok(Some(vertex))
|
Ok(Some(vertex))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn first_ancestors(
|
||||||
|
this: &(impl DagAlgorithm + ?Sized),
|
||||||
|
set: NameSet,
|
||||||
|
) -> Result<NameSet> {
|
||||||
|
let mut to_visit: Vec<VertexName> = {
|
||||||
|
let mut list = Vec::with_capacity(set.count().await?);
|
||||||
|
let mut iter = set.iter().await?;
|
||||||
|
while let Some(next) = iter.next().await {
|
||||||
|
let vertex = next?;
|
||||||
|
list.push(vertex);
|
||||||
|
}
|
||||||
|
list
|
||||||
|
};
|
||||||
|
let mut visited: HashSet<VertexName> = to_visit.clone().into_iter().collect();
|
||||||
|
while let Some(v) = to_visit.pop() {
|
||||||
|
#[allow(clippy::never_loop)]
|
||||||
|
if let Some(parent) = this.parent_names(v).await?.into_iter().next() {
|
||||||
|
if visited.insert(parent.clone()) {
|
||||||
|
to_visit.push(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let set = NameSet::from_iter(visited.into_iter().map(Ok));
|
||||||
|
this.sort(&set).await
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn heads(this: &(impl DagAlgorithm + ?Sized), set: NameSet) -> Result<NameSet> {
|
pub(crate) async fn heads(this: &(impl DagAlgorithm + ?Sized), set: NameSet) -> Result<NameSet> {
|
||||||
Ok(set.clone() - this.parents(set).await?)
|
Ok(set.clone() - this.parents(set).await?)
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,13 @@ macro_rules! delegate {
|
|||||||
{
|
{
|
||||||
self.$($t)*.ancestors(set)
|
self.$($t)*.ancestors(set)
|
||||||
}
|
}
|
||||||
|
fn first_ancestors<'a: 's, 's>(&'a self, set: $crate::Set)
|
||||||
|
-> std::pin::Pin<Box<dyn std::future::Future<Output=
|
||||||
|
$crate::Result<$crate::Set>
|
||||||
|
> + Send + 's>> where Self: 's
|
||||||
|
{
|
||||||
|
self.$($t)*.first_ancestors(set)
|
||||||
|
}
|
||||||
fn parents<'a: 's, 's>(&'a self, set: $crate::Set)
|
fn parents<'a: 's, 's>(&'a self, set: $crate::Set)
|
||||||
-> std::pin::Pin<Box<dyn std::future::Future<Output=
|
-> std::pin::Pin<Box<dyn std::future::Future<Output=
|
||||||
$crate::Result<$crate::Set>
|
$crate::Result<$crate::Set>
|
||||||
|
@ -57,6 +57,11 @@ pub trait DagAlgorithm: Send + Sync {
|
|||||||
default_impl::first_ancestor_nth(self, name, n).await
|
default_impl::first_ancestor_nth(self, name, n).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates ancestors but only follows the first parent.
|
||||||
|
async fn first_ancestors(&self, set: NameSet) -> Result<NameSet> {
|
||||||
|
default_impl::first_ancestors(self, set).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates heads of the given set.
|
/// Calculates heads of the given set.
|
||||||
async fn heads(&self, set: NameSet) -> Result<NameSet> {
|
async fn heads(&self, set: NameSet) -> Result<NameSet> {
|
||||||
default_impl::heads(self, set).await
|
default_impl::heads(self, set).await
|
||||||
|
Loading…
Reference in New Issue
Block a user