mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-04 05:28:02 +00:00
index: translate generation-filter range to item ranges
This allows us to merge overlapped ranges per entry.
This commit is contained in:
parent
c61d4e8404
commit
9a6a7c50db
1 changed files with 46 additions and 10 deletions
|
@ -1332,23 +1332,40 @@ impl<'a> Iterator for RevWalk<'a> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct RevWalkGenerationRange<'a> {
|
||||
queue: RevWalkQueue<'a, u32>,
|
||||
generation_range: Range<u32>,
|
||||
queue: RevWalkQueue<'a, RevWalkItemGenerationRange>,
|
||||
generation_end: u32,
|
||||
}
|
||||
|
||||
impl<'a> RevWalkGenerationRange<'a> {
|
||||
fn new(queue: RevWalkQueue<'a, ()>, 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),
|
||||
};
|
||||
RevWalkGenerationRange {
|
||||
queue: queue.map_wanted(|()| 0),
|
||||
generation_range,
|
||||
queue: queue.map_wanted(|()| item_range),
|
||||
generation_end: generation_range.end,
|
||||
}
|
||||
}
|
||||
|
||||
fn enqueue_wanted_parents(&mut self, entry: &IndexEntry<'_>, gen: u32) {
|
||||
if gen + 1 >= self.generation_range.end {
|
||||
fn enqueue_wanted_parents(&mut self, entry: &IndexEntry<'_>, gen: RevWalkItemGenerationRange) {
|
||||
// `gen.start` is incremented from 0, which should never overflow
|
||||
if gen.start + 1 >= self.generation_end {
|
||||
return;
|
||||
}
|
||||
self.queue.push_wanted_parents(entry, gen + 1);
|
||||
let succ_gen = RevWalkItemGenerationRange {
|
||||
start: gen.start + 1,
|
||||
end: gen.end.saturating_add(1),
|
||||
};
|
||||
self.queue.push_wanted_parents(entry, succ_gen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1358,7 +1375,7 @@ impl<'a> Iterator for RevWalkGenerationRange<'a> {
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(item) = self.queue.pop() {
|
||||
if let RevWalkWorkItemState::Wanted(mut known_gen) = item.state {
|
||||
let mut some_in_range = self.generation_range.contains(&known_gen);
|
||||
let mut some_in_range = known_gen.contains_end(self.generation_end);
|
||||
self.enqueue_wanted_parents(&item.entry.0, known_gen);
|
||||
while let Some(x) = self.queue.pop_eq(&item.entry.0) {
|
||||
// For wanted item, simply track all generation chains. This can
|
||||
|
@ -1368,7 +1385,7 @@ impl<'a> Iterator for RevWalkGenerationRange<'a> {
|
|||
// merge overlapping generation ranges.
|
||||
match x.state {
|
||||
RevWalkWorkItemState::Wanted(gen) if known_gen != gen => {
|
||||
some_in_range |= self.generation_range.contains(&gen);
|
||||
some_in_range |= gen.contains_end(self.generation_end);
|
||||
self.enqueue_wanted_parents(&item.entry.0, gen);
|
||||
known_gen = gen;
|
||||
}
|
||||
|
@ -1397,6 +1414,19 @@ impl<'a> Iterator for RevWalkGenerationRange<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
struct RevWalkItemGenerationRange {
|
||||
start: u32,
|
||||
end: u32,
|
||||
}
|
||||
|
||||
impl RevWalkItemGenerationRange {
|
||||
#[must_use]
|
||||
fn contains_end(self, end: u32) -> bool {
|
||||
self.start < end && end <= self.end
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexSegment for ReadonlyIndexImpl {
|
||||
fn segment_num_parent_commits(&self) -> u32 {
|
||||
self.num_parent_commits
|
||||
|
@ -2625,8 +2655,14 @@ mod tests {
|
|||
.collect_vec()
|
||||
};
|
||||
|
||||
// Simple generation bounds
|
||||
// Empty generation bounds
|
||||
assert_eq!(walk_commit_ids(&[&id_8].map(Clone::clone), &[], 0..0), []);
|
||||
assert_eq!(
|
||||
walk_commit_ids(&[&id_8].map(Clone::clone), &[], Range { start: 2, end: 1 }),
|
||||
[]
|
||||
);
|
||||
|
||||
// Simple generation bounds
|
||||
assert_eq!(
|
||||
walk_commit_ids(&[&id_2].map(Clone::clone), &[], 0..3),
|
||||
[&id_2, &id_1, &id_0].map(Clone::clone)
|
||||
|
|
Loading…
Reference in a new issue