mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-03 18:24:19 +00:00
index: construct RevWalk queue after item type is settled
It doesn't make sense to build BinaryHeap with intermediate type, and I'm going to reimplement take_until_roots() in a way that the queue drops uninteresting items.
This commit is contained in:
parent
8480ee9e05
commit
34fbaaaad6
1 changed files with 49 additions and 54 deletions
|
@ -110,16 +110,6 @@ impl<P, T> RevWalkWorkItem<P, T> {
|
|||
fn is_wanted(&self) -> bool {
|
||||
matches!(self.state, RevWalkWorkItemState::Wanted(_))
|
||||
}
|
||||
|
||||
fn map_wanted<U>(self, f: impl FnOnce(T) -> U) -> RevWalkWorkItem<P, U> {
|
||||
RevWalkWorkItem {
|
||||
pos: self.pos,
|
||||
state: match self.state {
|
||||
RevWalkWorkItemState::Wanted(t) => RevWalkWorkItemState::Wanted(f(t)),
|
||||
RevWalkWorkItemState::Unwanted => RevWalkWorkItemState::Unwanted,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -136,17 +126,6 @@ impl<P: Ord, T: Ord> RevWalkQueue<P, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_wanted<U: Ord>(self, mut f: impl FnMut(T) -> U) -> RevWalkQueue<P, U> {
|
||||
RevWalkQueue {
|
||||
items: self
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|x| x.map_wanted(&mut f))
|
||||
.collect(),
|
||||
unwanted_count: self.unwanted_count,
|
||||
}
|
||||
}
|
||||
|
||||
fn push_wanted(&mut self, pos: P, t: T) {
|
||||
let state = RevWalkWorkItemState::Wanted(t);
|
||||
self.items.push(RevWalkWorkItem { pos, state });
|
||||
|
@ -203,34 +182,38 @@ impl<P: Ord, T: Ord> RevWalkQueue<P, T> {
|
|||
#[must_use]
|
||||
pub(super) struct RevWalkBuilder<'a> {
|
||||
index: CompositeIndex<'a>,
|
||||
// TODO: Use Vec<_> until queued item type is settled.
|
||||
queue: RevWalkQueue<IndexPosition, ()>,
|
||||
wanted: Vec<IndexPosition>,
|
||||
unwanted: Vec<IndexPosition>,
|
||||
}
|
||||
|
||||
impl<'a> RevWalkBuilder<'a> {
|
||||
pub fn new(index: CompositeIndex<'a>) -> Self {
|
||||
let queue = RevWalkQueue::new();
|
||||
RevWalkBuilder { index, queue }
|
||||
RevWalkBuilder {
|
||||
index,
|
||||
wanted: Vec::new(),
|
||||
unwanted: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds head positions to be included.
|
||||
pub fn wanted_heads(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
||||
self.queue.extend_wanted(positions, ());
|
||||
self.wanted.extend(positions);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds root positions to be excluded. The roots precede the heads.
|
||||
pub fn unwanted_roots(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
||||
self.queue.extend_unwanted(positions);
|
||||
self.unwanted.extend(positions);
|
||||
self
|
||||
}
|
||||
|
||||
/// Walks ancestors.
|
||||
pub fn ancestors(self) -> RevWalkAncestors<'a> {
|
||||
RevWalkImpl {
|
||||
index: self.index,
|
||||
queue: self.queue,
|
||||
}
|
||||
let index = self.index;
|
||||
let mut queue = RevWalkQueue::new();
|
||||
queue.extend_wanted(self.wanted, ());
|
||||
queue.extend_unwanted(self.unwanted);
|
||||
RevWalkImpl { index, queue }
|
||||
}
|
||||
|
||||
/// Walks ancestors within the `generation_range`.
|
||||
|
@ -240,7 +223,16 @@ impl<'a> RevWalkBuilder<'a> {
|
|||
self,
|
||||
generation_range: Range<u32>,
|
||||
) -> RevWalkAncestorsGenerationRange<'a> {
|
||||
RevWalkGenerationRangeImpl::new(self.index, self.queue, generation_range)
|
||||
let index = self.index;
|
||||
let mut queue = RevWalkQueue::new();
|
||||
let item_range = RevWalkItemGenerationRange::from_filter_range(generation_range.clone());
|
||||
queue.extend_wanted(self.wanted, Reverse(item_range));
|
||||
queue.extend_unwanted(self.unwanted);
|
||||
RevWalkGenerationRangeImpl {
|
||||
index,
|
||||
queue,
|
||||
generation_end: generation_range.end,
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks ancestors until all of the reachable roots in `root_positions` get
|
||||
|
@ -293,14 +285,20 @@ impl<'a> RevWalkBuilder<'a> {
|
|||
let root_positions = Vec::from_iter(root_positions);
|
||||
let entries = self.ancestors_until_roots(&root_positions);
|
||||
let descendants_index = RevWalkDescendantsIndex::build(index, entries);
|
||||
|
||||
let mut queue = RevWalkQueue::new();
|
||||
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) {
|
||||
queue.push_wanted(Reverse(pos), ());
|
||||
queue.push_wanted(Reverse(pos), Reverse(item_range));
|
||||
}
|
||||
}
|
||||
RevWalkGenerationRangeImpl::new(descendants_index, queue, generation_range)
|
||||
RevWalkGenerationRangeImpl {
|
||||
index: descendants_index,
|
||||
queue,
|
||||
generation_end: generation_range.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,26 +356,6 @@ pub(super) struct RevWalkGenerationRangeImpl<'a, I: RevWalkIndex<'a>> {
|
|||
}
|
||||
|
||||
impl<'a, I: RevWalkIndex<'a>> RevWalkGenerationRangeImpl<'a, I> {
|
||||
fn new(index: I, queue: RevWalkQueue<I::Position, ()>, generation_range: Range<u32>) -> Self {
|
||||
// Translate filter range to item ranges so that overlapped ranges can be
|
||||
// merged later.
|
||||
//
|
||||
// Example: `generation_range = 1..4`
|
||||
// (original) (translated)
|
||||
// 0 1 2 3 4 0 1 2 3 4
|
||||
// *=====o generation_range + generation_end
|
||||
// + : : item's generation o=====* : item's range
|
||||
let item_range = RevWalkItemGenerationRange {
|
||||
start: 0,
|
||||
end: u32::saturating_sub(generation_range.end, generation_range.start),
|
||||
};
|
||||
RevWalkGenerationRangeImpl {
|
||||
index,
|
||||
queue: queue.map_wanted(|()| Reverse(item_range)),
|
||||
generation_end: generation_range.end,
|
||||
}
|
||||
}
|
||||
|
||||
fn enqueue_wanted_adjacents(
|
||||
&mut self,
|
||||
entry: &IndexEntry<'_>,
|
||||
|
@ -452,6 +430,23 @@ struct RevWalkItemGenerationRange {
|
|||
}
|
||||
|
||||
impl RevWalkItemGenerationRange {
|
||||
/// Translates filter range to item range so that overlapped ranges can be
|
||||
/// merged later.
|
||||
///
|
||||
/// Example: `generation_range = 1..4`
|
||||
/// ```text
|
||||
/// (original) (translated)
|
||||
/// 0 1 2 3 4 0 1 2 3 4
|
||||
/// *=====o generation_range + generation_end
|
||||
/// + : : item's generation o=====* : item's range
|
||||
/// ```
|
||||
fn from_filter_range(range: Range<u32>) -> Self {
|
||||
RevWalkItemGenerationRange {
|
||||
start: 0,
|
||||
end: u32::saturating_sub(range.end, range.start),
|
||||
}
|
||||
}
|
||||
|
||||
/// Suppose sorted ranges `self, other`, merges them if overlapped.
|
||||
#[must_use]
|
||||
fn try_merge_end(self, other: Self) -> Option<Self> {
|
||||
|
|
Loading…
Reference in a new issue