mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-05 20:55:05 +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 {
|
fn is_wanted(&self) -> bool {
|
||||||
matches!(self.state, RevWalkWorkItemState::Wanted(_))
|
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)]
|
#[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) {
|
fn push_wanted(&mut self, pos: P, t: T) {
|
||||||
let state = RevWalkWorkItemState::Wanted(t);
|
let state = RevWalkWorkItemState::Wanted(t);
|
||||||
self.items.push(RevWalkWorkItem { pos, state });
|
self.items.push(RevWalkWorkItem { pos, state });
|
||||||
|
@ -203,34 +182,38 @@ impl<P: Ord, T: Ord> RevWalkQueue<P, T> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(super) struct RevWalkBuilder<'a> {
|
pub(super) struct RevWalkBuilder<'a> {
|
||||||
index: CompositeIndex<'a>,
|
index: CompositeIndex<'a>,
|
||||||
// TODO: Use Vec<_> until queued item type is settled.
|
wanted: Vec<IndexPosition>,
|
||||||
queue: RevWalkQueue<IndexPosition, ()>,
|
unwanted: Vec<IndexPosition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RevWalkBuilder<'a> {
|
impl<'a> RevWalkBuilder<'a> {
|
||||||
pub fn new(index: CompositeIndex<'a>) -> Self {
|
pub fn new(index: CompositeIndex<'a>) -> Self {
|
||||||
let queue = RevWalkQueue::new();
|
RevWalkBuilder {
|
||||||
RevWalkBuilder { index, queue }
|
index,
|
||||||
|
wanted: Vec::new(),
|
||||||
|
unwanted: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds head positions to be included.
|
/// Adds head positions to be included.
|
||||||
pub fn wanted_heads(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
pub fn wanted_heads(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
||||||
self.queue.extend_wanted(positions, ());
|
self.wanted.extend(positions);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds root positions to be excluded. The roots precede the heads.
|
/// Adds root positions to be excluded. The roots precede the heads.
|
||||||
pub fn unwanted_roots(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
pub fn unwanted_roots(mut self, positions: impl IntoIterator<Item = IndexPosition>) -> Self {
|
||||||
self.queue.extend_unwanted(positions);
|
self.unwanted.extend(positions);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks ancestors.
|
/// Walks ancestors.
|
||||||
pub fn ancestors(self) -> RevWalkAncestors<'a> {
|
pub fn ancestors(self) -> RevWalkAncestors<'a> {
|
||||||
RevWalkImpl {
|
let index = self.index;
|
||||||
index: self.index,
|
let mut queue = RevWalkQueue::new();
|
||||||
queue: self.queue,
|
queue.extend_wanted(self.wanted, ());
|
||||||
}
|
queue.extend_unwanted(self.unwanted);
|
||||||
|
RevWalkImpl { index, queue }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks ancestors within the `generation_range`.
|
/// Walks ancestors within the `generation_range`.
|
||||||
|
@ -240,7 +223,16 @@ impl<'a> RevWalkBuilder<'a> {
|
||||||
self,
|
self,
|
||||||
generation_range: Range<u32>,
|
generation_range: Range<u32>,
|
||||||
) -> RevWalkAncestorsGenerationRange<'a> {
|
) -> 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
|
/// 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 root_positions = Vec::from_iter(root_positions);
|
||||||
let entries = self.ancestors_until_roots(&root_positions);
|
let entries = self.ancestors_until_roots(&root_positions);
|
||||||
let descendants_index = RevWalkDescendantsIndex::build(index, entries);
|
let descendants_index = RevWalkDescendantsIndex::build(index, entries);
|
||||||
|
|
||||||
let mut queue = RevWalkQueue::new();
|
let mut queue = RevWalkQueue::new();
|
||||||
|
let item_range = RevWalkItemGenerationRange::from_filter_range(generation_range.clone());
|
||||||
for pos in root_positions {
|
for pos in root_positions {
|
||||||
// Do not add unreachable roots which shouldn't be visited
|
// Do not add unreachable roots which shouldn't be visited
|
||||||
if descendants_index.contains_pos(pos) {
|
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> {
|
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(
|
fn enqueue_wanted_adjacents(
|
||||||
&mut self,
|
&mut self,
|
||||||
entry: &IndexEntry<'_>,
|
entry: &IndexEntry<'_>,
|
||||||
|
@ -452,6 +430,23 @@ struct RevWalkItemGenerationRange {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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.
|
/// Suppose sorted ranges `self, other`, merges them if overlapped.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn try_merge_end(self, other: Self) -> Option<Self> {
|
fn try_merge_end(self, other: Self) -> Option<Self> {
|
||||||
|
|
Loading…
Reference in a new issue