mirror of
https://github.com/martinvonz/jj.git
synced 2024-10-24 15:43:12 +00:00
index: turn CompositeIndex::walk_revs() into position-based API
This gets rid of round-trip conversion from queries like "(main..)-". I have such expression in my default log/disambiguation revset, and the query could take ~150ms to convert head positions back and forth if the repository had tons of unmerged commits.
This commit is contained in:
parent
8b0c01d1e9
commit
a67d8b5a65
3 changed files with 73 additions and 58 deletions
|
@ -888,7 +888,7 @@ impl<'a> CompositeIndex<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition> {
|
||||
pub fn commit_id_to_pos(&self, commit_id: &CommitId) -> Option<IndexPosition> {
|
||||
self.ancestor_index_segments()
|
||||
.find_map(|segment| segment.segment_commit_id_to_pos(commit_id))
|
||||
}
|
||||
|
@ -991,12 +991,12 @@ impl<'a> CompositeIndex<'a> {
|
|||
self.heads_pos(result)
|
||||
}
|
||||
|
||||
pub fn walk_revs(&self, wanted: &[CommitId], unwanted: &[CommitId]) -> RevWalk<'a> {
|
||||
pub fn walk_revs(&self, wanted: &[IndexPosition], unwanted: &[IndexPosition]) -> RevWalk<'a> {
|
||||
let mut rev_walk = RevWalk::new(*self);
|
||||
for pos in wanted.iter().map(|id| self.commit_id_to_pos(id).unwrap()) {
|
||||
for &pos in wanted {
|
||||
rev_walk.add_wanted(pos);
|
||||
}
|
||||
for pos in unwanted.iter().map(|id| self.commit_id_to_pos(id).unwrap()) {
|
||||
for &pos in unwanted {
|
||||
rev_walk.add_unwanted(pos);
|
||||
}
|
||||
rev_walk
|
||||
|
@ -2041,6 +2041,13 @@ mod tests {
|
|||
move || iter.next().unwrap()
|
||||
}
|
||||
|
||||
fn to_positions_vec(index: CompositeIndex<'_>, commit_ids: &[CommitId]) -> Vec<IndexPosition> {
|
||||
commit_ids
|
||||
.iter()
|
||||
.map(|id| index.commit_id_to_pos(id).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test_case(false; "memory")]
|
||||
#[test_case(true; "file")]
|
||||
fn index_empty(on_disk: bool) {
|
||||
|
@ -2743,9 +2750,11 @@ mod tests {
|
|||
index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
|
||||
|
||||
let walk_commit_ids = |wanted: &[CommitId], unwanted: &[CommitId]| {
|
||||
let index = index.as_composite();
|
||||
let wanted_positions = to_positions_vec(index, wanted);
|
||||
let unwanted_positions = to_positions_vec(index, unwanted);
|
||||
index
|
||||
.as_composite()
|
||||
.walk_revs(wanted, unwanted)
|
||||
.walk_revs(&wanted_positions, &unwanted_positions)
|
||||
.map(|entry| entry.commit_id())
|
||||
.collect_vec()
|
||||
};
|
||||
|
@ -2833,9 +2842,11 @@ mod tests {
|
|||
index.add_commit_data(id_8.clone(), new_change_id(), &[id_7.clone()]);
|
||||
|
||||
let walk_commit_ids = |wanted: &[CommitId], unwanted: &[CommitId], range: Range<u32>| {
|
||||
let index = index.as_composite();
|
||||
let wanted_positions = to_positions_vec(index, wanted);
|
||||
let unwanted_positions = to_positions_vec(index, unwanted);
|
||||
index
|
||||
.as_composite()
|
||||
.walk_revs(wanted, unwanted)
|
||||
.walk_revs(&wanted_positions, &unwanted_positions)
|
||||
.filter_by_generation(range)
|
||||
.map(|entry| entry.commit_id())
|
||||
.collect_vec()
|
||||
|
@ -2910,9 +2921,10 @@ mod tests {
|
|||
);
|
||||
|
||||
let walk_commit_ids = |wanted: &[CommitId], range: Range<u32>| {
|
||||
let index = index.as_composite();
|
||||
let wanted_positions = to_positions_vec(index, wanted);
|
||||
index
|
||||
.as_composite()
|
||||
.walk_revs(wanted, &[])
|
||||
.walk_revs(&wanted_positions, &[])
|
||||
.filter_by_generation(range)
|
||||
.map(|entry| entry.commit_id())
|
||||
.collect_vec()
|
||||
|
@ -2980,13 +2992,11 @@ mod tests {
|
|||
|
||||
let visible_heads = [&id_6, &id_8].map(Clone::clone);
|
||||
let walk_commit_ids = |roots: &[CommitId], heads: &[CommitId], range: Range<u32>| {
|
||||
let root_positions = roots
|
||||
.iter()
|
||||
.map(|id| index.as_composite().commit_id_to_pos(id).unwrap())
|
||||
.collect_vec();
|
||||
let index = index.as_composite();
|
||||
let root_positions = to_positions_vec(index, roots);
|
||||
let head_positions = to_positions_vec(index, heads);
|
||||
index
|
||||
.as_composite()
|
||||
.walk_revs(heads, &[])
|
||||
.walk_revs(&head_positions, &[])
|
||||
.descendants_filtered_by_generation(&root_positions, range)
|
||||
.map(|entry| entry.commit_id())
|
||||
.collect_vec()
|
||||
|
|
|
@ -535,10 +535,10 @@ impl<'index> EvaluationContext<'index> {
|
|||
generation,
|
||||
} => {
|
||||
let root_set = self.evaluate(roots)?;
|
||||
let root_ids = root_set.iter().map(|entry| entry.commit_id()).collect_vec();
|
||||
let root_positions = root_set.iter().map(|entry| entry.position()).collect_vec();
|
||||
let head_set = self.evaluate(heads)?;
|
||||
let head_ids = head_set.iter().map(|entry| entry.commit_id()).collect_vec();
|
||||
let walk = self.index.walk_revs(&head_ids, &root_ids);
|
||||
let head_positions = head_set.iter().map(|entry| entry.position()).collect_vec();
|
||||
let walk = self.index.walk_revs(&head_positions, &root_positions);
|
||||
if generation == &GENERATION_RANGE_FULL {
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
} else {
|
||||
|
@ -662,8 +662,8 @@ impl<'index> EvaluationContext<'index> {
|
|||
where
|
||||
S: InternalRevset<'a> + ?Sized,
|
||||
{
|
||||
let head_ids = head_set.iter().map(|entry| entry.commit_id()).collect_vec();
|
||||
self.index.walk_revs(&head_ids, &[])
|
||||
let head_positions = head_set.iter().map(|entry| entry.position()).collect_vec();
|
||||
self.index.walk_revs(&head_positions, &[])
|
||||
}
|
||||
|
||||
fn walk_children<'a, 'b, S, T>(
|
||||
|
|
|
@ -17,7 +17,9 @@ use std::sync::Arc;
|
|||
use jujutsu_lib::backend::CommitId;
|
||||
use jujutsu_lib::commit::Commit;
|
||||
use jujutsu_lib::commit_builder::CommitBuilder;
|
||||
use jujutsu_lib::default_index_store::{CompositeIndex, MutableIndexImpl, ReadonlyIndexWrapper};
|
||||
use jujutsu_lib::default_index_store::{
|
||||
CompositeIndex, IndexPosition, MutableIndexImpl, ReadonlyIndexWrapper,
|
||||
};
|
||||
use jujutsu_lib::index::Index as _;
|
||||
use jujutsu_lib::repo::{MutableRepo, ReadonlyRepo, Repo};
|
||||
use jujutsu_lib::settings::UserSettings;
|
||||
|
@ -39,6 +41,13 @@ fn generation_number(index: CompositeIndex, commit_id: &CommitId) -> u32 {
|
|||
index.entry_by_id(commit_id).unwrap().generation_number()
|
||||
}
|
||||
|
||||
fn to_positions_vec(index: CompositeIndex<'_>, commit_ids: &[CommitId]) -> Vec<IndexPosition> {
|
||||
commit_ids
|
||||
.iter()
|
||||
.map(|id| index.commit_id_to_pos(id).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test_case(false ; "local backend")]
|
||||
#[test_case(true ; "git backend")]
|
||||
fn test_index_commits_empty_repo(use_git: bool) {
|
||||
|
@ -188,72 +197,68 @@ fn test_index_commits_criss_cross(use_git: bool) {
|
|||
}
|
||||
}
|
||||
|
||||
let walk_revs = |wanted: &[CommitId], unwanted: &[CommitId]| {
|
||||
let wanted_positions = to_positions_vec(index, wanted);
|
||||
let unwanted_positions = to_positions_vec(index, unwanted);
|
||||
index.walk_revs(&wanted_positions, &unwanted_positions)
|
||||
};
|
||||
|
||||
// RevWalk deduplicates chains by entry.
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(&[left_commits[num_generations - 1].id().clone()], &[])
|
||||
.count(),
|
||||
walk_revs(&[left_commits[num_generations - 1].id().clone()], &[]).count(),
|
||||
2 * num_generations
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(&[right_commits[num_generations - 1].id().clone()], &[])
|
||||
.count(),
|
||||
walk_revs(&[right_commits[num_generations - 1].id().clone()], &[]).count(),
|
||||
2 * num_generations
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(
|
||||
&[left_commits[num_generations - 1].id().clone()],
|
||||
&[left_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.count(),
|
||||
walk_revs(
|
||||
&[left_commits[num_generations - 1].id().clone()],
|
||||
&[left_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(
|
||||
&[right_commits[num_generations - 1].id().clone()],
|
||||
&[right_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.count(),
|
||||
walk_revs(
|
||||
&[right_commits[num_generations - 1].id().clone()],
|
||||
&[right_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
|
||||
// RevWalkGenerationRange deduplicates chains by (entry, generation), which may
|
||||
// be more expensive than RevWalk, but should still finish in reasonable time.
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(&[left_commits[num_generations - 1].id().clone()], &[])
|
||||
walk_revs(&[left_commits[num_generations - 1].id().clone()], &[])
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
2 * num_generations
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(&[right_commits[num_generations - 1].id().clone()], &[])
|
||||
walk_revs(&[right_commits[num_generations - 1].id().clone()], &[])
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
2 * num_generations
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(
|
||||
&[left_commits[num_generations - 1].id().clone()],
|
||||
&[left_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
walk_revs(
|
||||
&[left_commits[num_generations - 1].id().clone()],
|
||||
&[left_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
index
|
||||
.walk_revs(
|
||||
&[right_commits[num_generations - 1].id().clone()],
|
||||
&[right_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
walk_revs(
|
||||
&[right_commits[num_generations - 1].id().clone()],
|
||||
&[right_commits[num_generations - 2].id().clone()]
|
||||
)
|
||||
.filter_by_generation(0..(num_generations + 1) as u32)
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue