1162 lines · 40.8 KB · Rust
RawDownload
// Copyright 2023 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use std::cmp::Reverse;use std::cmp::max;use std::collections::HashMap;use std::collections::HashSet;use std::iter::Fuse;use std::iter::FusedIterator;use std::ops::Range; use smallvec::SmallVec; use super::composite::CompositeCommitIndex;use super::composite::CompositeIndex;use super::entry::GlobalCommitPosition;use super::entry::SmallGlobalCommitPositionsVec;use super::rev_walk_queue::RevWalkQueue;use super::rev_walk_queue::RevWalkWorkItem;use crate::revset::PARENTS_RANGE_FULL; /// Like `Iterator`, but doesn't borrow the `index` internally.pub(super) trait RevWalk<I: ?Sized> {    type Item;     /// Advances the iteration and returns the next item.    ///    /// The caller must provide the same `index` instance.    ///    /// Returns `None` when the iteration is finished. Once `None` is returned,    /// this will never resume. In other words, a `RevWalk` is fused.    fn next(&mut self, index: &I) -> Option<Self::Item>;     // The following methods are provided for convenience. They are not supposed    // to be reimplemented.     /// Wraps in adapter that will filter and transform items by the given    /// function.    fn filter_map<B, F>(self, f: F) -> FilterMapRevWalk<Self, F>    where        Self: Sized,        F: FnMut(&I, Self::Item) -> Option<B>,    {        FilterMapRevWalk { walk: self, f }    }     /// Wraps in adapter that will transform items by the given function.    fn map<B, F>(self, f: F) -> MapRevWalk<Self, F>    where        Self: Sized,        F: FnMut(&I, Self::Item) -> B,    {        MapRevWalk { walk: self, f }    }     /// Wraps in adapter that can peek one more item without consuming.    fn peekable(self) -> PeekableRevWalk<I, Self>    where        Self: Sized,    {        PeekableRevWalk {            walk: self,            peeked: None,        }    }     /// Reattaches the underlying `index`.    fn attach(self, index: &I) -> RevWalkBorrowedIndexIter<'_, I, Self>    where        Self: Sized,    {        RevWalkBorrowedIndexIter { index, walk: self }    }} impl<I: ?Sized, W: RevWalk<I> + ?Sized> RevWalk<I> for Box<W> {    type Item = W::Item;     fn next(&mut self, index: &I) -> Option<Self::Item> {        <W as RevWalk<I>>::next(self, index)    }} /// Adapter that turns `Iterator` into `RevWalk` by dropping index argument.////// As the name suggests, the source object is usually a slice or `Vec`.#[derive(Clone, Debug)]pub(super) struct EagerRevWalk<T> {    iter: Fuse<T>,} impl<T: Iterator> EagerRevWalk<T> {    pub fn new(iter: T) -> Self {        Self { iter: iter.fuse() }    }} impl<I: ?Sized, T: Iterator> RevWalk<I> for EagerRevWalk<T> {    type Item = T::Item;     fn next(&mut self, _index: &I) -> Option<Self::Item> {        self.iter.next()    }} #[derive(Clone, Debug)]#[must_use]pub(super) struct FilterMapRevWalk<W, F> {    walk: W,    f: F,} impl<B, I, W, F> RevWalk<I> for FilterMapRevWalk<W, F>where    I: ?Sized,    W: RevWalk<I>,    F: FnMut(&I, W::Item) -> Option<B>,{    type Item = B;     fn next(&mut self, index: &I) -> Option<Self::Item> {        while let Some(item) = self.walk.next(index) {            if let Some(new_item) = (self.f)(index, item) {                return Some(new_item);            }        }        None    }} #[derive(Clone, Debug)]#[must_use]pub(super) struct MapRevWalk<W, F> {    walk: W,    f: F,} impl<B, I, W, F> RevWalk<I> for MapRevWalk<W, F>where    I: ?Sized,    W: RevWalk<I>,    F: FnMut(&I, W::Item) -> B,{    type Item = B;     fn next(&mut self, index: &I) -> Option<Self::Item> {        self.walk.next(index).map(|item| (self.f)(index, item))    }} #[derive(Clone, Debug)]#[must_use]pub(super) struct PeekableRevWalk<I: ?Sized, W: RevWalk<I>> {    walk: W,    // Since RevWalk is fused, we don't need a nested Option<Option<_>>.    peeked: Option<W::Item>,} impl<I: ?Sized, W: RevWalk<I>> PeekableRevWalk<I, W> {    pub fn peek(&mut self, index: &I) -> Option<&W::Item> {        if self.peeked.is_none() {            self.peeked = self.walk.next(index);        }        self.peeked.as_ref()    }     pub fn next_if(        &mut self,        index: &I,        predicate: impl FnOnce(&W::Item) -> bool,    ) -> Option<W::Item> {        match self.next(index) {            Some(item) if predicate(&item) => Some(item),            other => {                assert!(self.peeked.is_none());                self.peeked = other;                None            }        }    }} impl<I: ?Sized, W: RevWalk<I>> RevWalk<I> for PeekableRevWalk<I, W> {    type Item = W::Item;     fn next(&mut self, index: &I) -> Option<Self::Item> {        self.peeked.take().or_else(|| self.walk.next(index))    }} /// Adapter that turns `RevWalk` into `Iterator` by attaching borrowed `index`.#[derive(Clone, Debug)]#[must_use]pub(super) struct RevWalkBorrowedIndexIter<'a, I: ?Sized, W> {    index: &'a I,    walk: W,} impl<I: ?Sized, W> RevWalkBorrowedIndexIter<'_, I, W> {    /// Turns into `'static`-lifetime walk object by detaching the index.    pub fn detach(self) -> W {        self.walk    }} impl<I: ?Sized, W: RevWalk<I>> Iterator for RevWalkBorrowedIndexIter<'_, I, W> {    type Item = W::Item;     fn next(&mut self) -> Option<Self::Item> {        self.walk.next(self.index)    }} impl<I: ?Sized, W: RevWalk<I>> FusedIterator for RevWalkBorrowedIndexIter<'_, I, W> {} /// Adapter that turns `RevWalk` into `Iterator` by attaching owned `index`.#[derive(Clone, Debug)]#[must_use]pub(super) struct RevWalkOwnedIndexIter<I, W> {    index: I,    walk: W,} impl<I, W: RevWalk<I>> Iterator for RevWalkOwnedIndexIter<I, W> {    type Item = W::Item;     fn next(&mut self) -> Option<Self::Item> {        self.walk.next(&self.index)    }} impl<I, W: RevWalk<I>> FusedIterator for RevWalkOwnedIndexIter<I, W> {} pub(super) trait RevWalkIndex {    type Position: Copy + Ord;    type AdjacentPositions: IntoIterator<Item = Self::Position> + AsRef<[Self::Position]>;     fn adjacent_positions(&self, pos: Self::Position) -> Self::AdjacentPositions;} impl RevWalkIndex for CompositeIndex {    type Position = GlobalCommitPosition;    type AdjacentPositions = SmallGlobalCommitPositionsVec;     fn adjacent_positions(&self, pos: Self::Position) -> Self::AdjacentPositions {        self.commits().entry_by_pos(pos).parent_positions()    }} #[derive(Clone)]pub(super) struct RevWalkDescendantsIndex {    children_map: HashMap<GlobalCommitPosition, DescendantIndexPositionsVec>,} // See SmallGlobalCommitPositionsVec for the array size.type DescendantIndexPositionsVec = SmallVec<[Reverse<GlobalCommitPosition>; 4]>; impl RevWalkDescendantsIndex {    fn build(        index: &CompositeCommitIndex,        positions: impl IntoIterator<Item = GlobalCommitPosition>,    ) -> Self {        // For dense set, it's probably cheaper to use `Vec` instead of `HashMap`.        let mut children_map: HashMap<GlobalCommitPosition, DescendantIndexPositionsVec> =            HashMap::new();        for pos in positions {            children_map.entry(pos).or_default(); // mark head node            for parent_pos in index.entry_by_pos(pos).parent_positions() {                let parent = children_map.entry(parent_pos).or_default();                parent.push(Reverse(pos));            }        }         Self { children_map }    }     fn contains_pos(&self, pos: GlobalCommitPosition) -> bool {        self.children_map.contains_key(&pos)    }} impl RevWalkIndex for RevWalkDescendantsIndex {    type Position = Reverse<GlobalCommitPosition>;    type AdjacentPositions = DescendantIndexPositionsVec;     fn adjacent_positions(&self, pos: Self::Position) -> Self::AdjacentPositions {        self.children_map[&pos.0].clone()    }} #[derive(Clone)]#[must_use]pub(super) struct RevWalkBuilder<'a> {    index: &'a CompositeIndex,    wanted: Vec<GlobalCommitPosition>,    unwanted: Vec<GlobalCommitPosition>,    wanted_parents_range: Range<u32>,} impl<'a> RevWalkBuilder<'a> {    pub fn new(index: &'a CompositeIndex) -> Self {        Self {            index,            wanted: Vec::new(),            unwanted: Vec::new(),            wanted_parents_range: PARENTS_RANGE_FULL,        }    }     /// Sets head positions to be included.    pub fn wanted_heads(mut self, positions: Vec<GlobalCommitPosition>) -> Self {        self.wanted = positions;        self    }     /// Sets range of parents to iterate over for wanted heads.    pub fn wanted_parents_range(mut self, wanted_parents_range: Range<u32>) -> Self {        assert!(wanted_parents_range.start <= wanted_parents_range.end);        self.wanted_parents_range = wanted_parents_range;        self    }     /// Sets root positions to be excluded. The roots precede the heads.    pub fn unwanted_roots(mut self, positions: Vec<GlobalCommitPosition>) -> Self {        self.unwanted = positions;        self    }     /// Walks ancestors.    pub fn ancestors(self) -> RevWalkAncestors<'a> {        self.ancestors_with_min_pos(GlobalCommitPosition::MIN)    }     fn ancestors_with_min_pos(self, min_pos: GlobalCommitPosition) -> RevWalkAncestors<'a> {        let index = self.index;        let wanted_parents_range = self.wanted_parents_range;        let mut wanted_queue = RevWalkQueue::with_min_pos(min_pos);        let mut unwanted_queue = RevWalkQueue::with_min_pos(min_pos);        wanted_queue.extend(self.wanted, ());        unwanted_queue.extend(self.unwanted, ());        RevWalkBorrowedIndexIter {            index,            walk: RevWalkImpl {                wanted_queue,                unwanted_queue,                wanted_parents_range,            },        }    }     /// Walks ancestors within the `generation_range`.    ///    /// A generation number counts from the heads.    pub fn ancestors_filtered_by_generation(        self,        generation_range: Range<u32>,    ) -> RevWalkAncestorsGenerationRange<'a> {        let index = self.index;        let wanted_parents_range = self.wanted_parents_range;        let mut wanted_queue = RevWalkQueue::with_min_pos(GlobalCommitPosition::MIN);        let mut unwanted_queue = RevWalkQueue::with_min_pos(GlobalCommitPosition::MIN);        let item_range = RevWalkItemGenerationRange::from_filter_range(generation_range.clone());        wanted_queue.extend(self.wanted, Reverse(item_range));        unwanted_queue.extend(self.unwanted, ());        RevWalkBorrowedIndexIter {            index,            walk: RevWalkGenerationRangeImpl {                wanted_queue,                unwanted_queue,                wanted_parents_range,                generation_end: generation_range.end,            },        }    }     /// 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 ancestors_until_roots(        self,        root_positions: impl IntoIterator<Item = GlobalCommitPosition>,    ) -> RevWalkAncestors<'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/jj-vcs/jj/pull/1492#discussion_r1160678325        let min_pos = root_positions            .into_iter()            .min()            .unwrap_or(GlobalCommitPosition::MAX);        self.ancestors_with_min_pos(min_pos)    }     /// Fully consumes ancestors and walks back from the `root_positions`.    ///    /// The returned iterator yields entries in order of ascending index    /// position.    pub fn descendants(        self,        root_positions: HashSet<GlobalCommitPosition>,    ) -> RevWalkDescendants<'a> {        let index = self.index;        let candidate_positions = self            .ancestors_until_roots(root_positions.iter().copied())            .collect();        RevWalkBorrowedIndexIter {            index,            walk: RevWalkDescendantsImpl {                candidate_positions,                root_positions,                reachable_positions: HashSet::new(),            },        }    }     /// Fully consumes ancestors and walks back from the `root_positions` within    /// the `generation_range`.    ///    /// A generation number counts from the roots.    ///    /// The returned iterator yields entries in order of ascending index    /// position.    pub fn descendants_filtered_by_generation(        self,        root_positions: Vec<GlobalCommitPosition>,        generation_range: Range<u32>,    ) -> RevWalkDescendantsGenerationRange {        let index = self.index;        let positions = self.ancestors_until_roots(root_positions.iter().copied());        let descendants_index = RevWalkDescendantsIndex::build(index.commits(), positions);         let mut wanted_queue = RevWalkQueue::with_min_pos(Reverse(GlobalCommitPosition::MAX));        let unwanted_queue = RevWalkQueue::with_min_pos(Reverse(GlobalCommitPosition::MAX));        let item_range = RevWalkItemGenerationRange::from_filter_range(generation_range.clone());        for pos in root_positions {            // Do not add unreachable roots which shouldn't be visited            if descendants_index.contains_pos(pos) {                wanted_queue.push(Reverse(pos), Reverse(item_range));            }        }        RevWalkOwnedIndexIter {            index: descendants_index,            walk: RevWalkGenerationRangeImpl {                wanted_queue,                unwanted_queue,                // Since we're using the descendants index, this actually is a range for the                // children instead of the parents.                wanted_parents_range: PARENTS_RANGE_FULL,                generation_end: generation_range.end,            },        }    }} pub(super) type RevWalkAncestors<'a> =    RevWalkBorrowedIndexIter<'a, CompositeIndex, RevWalkImpl<GlobalCommitPosition>>; #[derive(Clone)]#[must_use]pub(super) struct RevWalkImpl<P> {    wanted_queue: RevWalkQueue<P, ()>,    unwanted_queue: RevWalkQueue<P, ()>,    wanted_parents_range: Range<u32>,} impl<I: RevWalkIndex + ?Sized> RevWalk<I> for RevWalkImpl<I::Position> {    type Item = I::Position;     fn next(&mut self, index: &I) -> Option<Self::Item> {        while let Some(item) = self.wanted_queue.pop() {            self.wanted_queue.skip_while_eq(&item.pos);            if flush_queue_until(&mut self.unwanted_queue, index, item.pos).is_some() {                continue;            }            let parents = index.adjacent_positions(item.pos);            self.wanted_queue.extend(                filter_slice_by_range(parents.as_ref(), &self.wanted_parents_range)                    .iter()                    .copied(),                (),            );            return Some(item.pos);        }        None    }} pub(super) type RevWalkAncestorsGenerationRange<'a> =

Lines 1–500 of 1162.