index: migrate walk_ancestors_until_roots() from revset engine

I'm going to add a RevWalk method to walk descendants with generation filter,
which will use this helper method. RevWalk::take_until_roots() uses .min()
instead of .last() since RevWalk shouldn't know the order of the input set.
This commit is contained in:
Yuya Nishihara 2023-04-22 17:32:58 +09:00
parent 6e8d0a0860
commit e6740d9c3b
2 changed files with 26 additions and 29 deletions

View file

@ -1302,6 +1302,22 @@ impl<'a> RevWalk<'a> {
pub fn filter_by_generation(self, generation_range: Range<u32>) -> RevWalkGenerationRange<'a> {
RevWalkGenerationRange::new(self.queue, generation_range)
}
/// Walks ancestors until all of the reachable roots in `root_positions` get
/// visited.
///
/// Use this if you are only interested in descendants of the given roots.
/// The caller still needs to filter out unwanted entries.
pub fn take_until_roots(
self,
root_positions: &[IndexPosition],
) -> impl Iterator<Item = IndexEntry<'a>> + Clone + 'a {
// We can also make it stop visiting based on the generation number. Maybe
// it will perform better for unbalanced branchy history.
// https://github.com/martinvonz/jj/pull/1492#discussion_r1160678325
let bottom_position = *root_positions.iter().min().unwrap_or(&IndexPosition::MAX);
self.take_while(move |entry| entry.position() >= bottom_position)
}
}
impl<'a> Iterator for RevWalk<'a> {

View file

@ -723,41 +723,19 @@ impl<'index> EvaluationContext<'index> {
self.composite_index.walk_revs(&head_ids, &[])
}
fn walk_ancestors_until_roots<'a, 'b, S, T>(
&self,
root_set: &S,
head_set: &T,
) -> (
impl Iterator<Item = IndexEntry<'index>> + Clone + 'index,
Vec<IndexPosition>,
)
where
S: InternalRevset<'a> + ?Sized,
T: InternalRevset<'b> + ?Sized,
{
// We can also make RevWalk stop visiting based on the generation number. Maybe
// it will perform better for unbalanced branchy history.
// https://github.com/martinvonz/jj/pull/1492#discussion_r1160678325
let root_positions = root_set.iter().map(|entry| entry.position()).collect_vec();
let bottom_position = *root_positions.last().unwrap_or(&IndexPosition::MAX);
let walk = self
.walk_ancestors(head_set)
.take_while(move |entry| entry.position() >= bottom_position);
(walk, root_positions)
}
fn walk_children<'a, 'b, S, T>(
&self,
root_set: &S,
head_set: &T,
) -> impl InternalRevset<'index> + 'index
where
// TODO: 'index shouldn't be required, but rustc 1.64.0 failed to deduce lifetime of
// walk. The problem appears to be fixed somewhere between 1.64.0 and 1.69.0.
S: InternalRevset<'a> + ?Sized + 'index,
T: InternalRevset<'b> + ?Sized + 'index,
S: InternalRevset<'a> + ?Sized,
T: InternalRevset<'b> + ?Sized,
{
let (walk, root_positions) = self.walk_ancestors_until_roots(root_set, head_set);
let root_positions = root_set.iter().map(|entry| entry.position()).collect_vec();
let walk = self
.walk_ancestors(head_set)
.take_until_roots(&root_positions);
let root_positions: HashSet<_> = root_positions.into_iter().collect();
let candidates = Box::new(RevWalkRevset { walk });
let predicate = PurePredicateFn(move |entry: &IndexEntry| {
@ -784,7 +762,10 @@ impl<'index> EvaluationContext<'index> {
S: InternalRevset<'a> + ?Sized,
T: InternalRevset<'b> + ?Sized,
{
let (walk, root_positions) = self.walk_ancestors_until_roots(root_set, head_set);
let root_positions = root_set.iter().map(|entry| entry.position()).collect_vec();
let walk = self
.walk_ancestors(head_set)
.take_until_roots(&root_positions);
let root_positions: HashSet<_> = root_positions.into_iter().collect();
let mut reachable_positions = HashSet::new();
let mut index_entries = vec![];