revset: do not scan ancestors more than once to evaluate nested children set

This commit is contained in:
Yuya Nishihara 2023-04-21 18:12:10 +09:00
parent 524db833f7
commit d948acd5bf
2 changed files with 30 additions and 11 deletions

View file

@ -618,18 +618,28 @@ impl<'index> EvaluationContext<'index> {
heads,
generation_from_roots,
} => {
let mut root_set = self.evaluate(roots)?;
let root_set = self.evaluate(roots)?;
let head_set = self.evaluate(heads)?;
// TODO: implement generic evaluation path for generation filter
for _ in 0..generation_from_roots.start {
root_set = Box::new(self.walk_children(&*root_set, &*head_set));
}
if generation_from_roots.end == generation_from_roots.start + 1 {
Ok(root_set)
} else {
assert_eq!(generation_from_roots.end, u64::MAX); // TODO
if generation_from_roots == &(1..2) {
Ok(Box::new(self.walk_children(&*root_set, &*head_set)))
} else if generation_from_roots == &GENERATION_RANGE_FULL {
let (dag_range_set, _) = self.collect_dag_range(&*root_set, &*head_set);
Ok(Box::new(dag_range_set))
} else {
// For small generation range, it might be better to build a reachable map
// with generation bit set, which can be calculated incrementally from roots:
// reachable[pos] = (reachable[parent_pos] | ...) << 1
let root_positions =
root_set.iter().map(|entry| entry.position()).collect_vec();
let walk = self
.walk_ancestors(&*head_set)
.descendants_filtered_by_generation(
&root_positions,
to_u32_generation_range(generation_from_roots)?,
);
let mut index_entries = walk.collect_vec();
index_entries.reverse();
Ok(Box::new(EagerRevset { index_entries }))
}
}
ResolvedExpression::Heads(candidates) => {

View file

@ -13,7 +13,6 @@ v2.40.0
v2.39.0..v2.40.0
:v2.40.0 ~ :v2.39.0
v2.39.0:v2.40.0
v2.40.0+
# Tags and branches
tags()
branches()
@ -42,16 +41,26 @@ heads(:v2.40.0)
v1.0.0-
v1.0.0---
:v1.0.0---
# Children and descendants of old commit
v1.0.0+
v1.0.0+++
v1.0.0+++:
# Parents and ancestors of recent commit
v2.40.0-
v2.40.0---
:v2.40.0---
# Children and descendants of recent commit
v2.40.0+
v2.40.0+++
v2.40.0+++:
# Parents and ancestors of small subset
tags()-
tags()---
:tags()---
# Children of small subset
# Children and descendants of small subset
tags()+
tags()+++
tags()+++:
# Filter that doesn't read commit object
merges()
~merges()