ok/jj
1
0
Fork 0
forked from mirrors/jj

index: leverage ancestor iterator to collect segments to be squashed

I think "for" loop is easier to follow. Maybe it could be rewritten further to
.find_map() loop, but that would be too clever.

I also made ancestor_index_segments() pub(super) since it doesn't make sense
to only provide ancestor_files_without_local().
This commit is contained in:
Yuya Nishihara 2023-12-19 20:09:23 +09:00
parent 55b4f69fb6
commit 1d80bbb70a
2 changed files with 20 additions and 22 deletions

View file

@ -91,12 +91,16 @@ impl<'a> CompositeIndex<'a> {
CompositeIndex(segment)
}
fn ancestor_files_without_local(&self) -> impl Iterator<Item = &'a Arc<ReadonlyIndexSegment>> {
/// Iterates parent and its ancestor readonly index segments.
pub(super) fn ancestor_files_without_local(
&self,
) -> impl Iterator<Item = &'a Arc<ReadonlyIndexSegment>> {
let parent_file = self.0.segment_parent_file();
iter::successors(parent_file, |file| file.segment_parent_file())
}
fn ancestor_index_segments(&self) -> impl Iterator<Item = &'a dyn IndexSegment> {
/// Iterates self and its ancestor index segments.
pub(super) fn ancestor_index_segments(&self) -> impl Iterator<Item = &'a dyn IndexSegment> {
iter::once(self.0).chain(
self.ancestor_files_without_local()
.map(|file| file.as_ref() as &dyn IndexSegment),

View file

@ -240,33 +240,27 @@ impl MutableIndexSegment {
fn maybe_squash_with_ancestors(self) -> MutableIndexSegment {
let mut num_new_commits = self.segment_num_commits();
let mut files_to_squash = vec![];
let mut maybe_parent_file = self.parent_file.clone();
let mut squashed;
loop {
match maybe_parent_file {
Some(parent_file) => {
// TODO: We should probably also squash if the parent file has less than N
// commits, regardless of how many (few) are in `self`.
if 2 * num_new_commits < parent_file.segment_num_commits() {
squashed = MutableIndexSegment::incremental(parent_file);
break;
}
num_new_commits += parent_file.segment_num_commits();
files_to_squash.push(parent_file.clone());
maybe_parent_file = parent_file.segment_parent_file().cloned();
}
None => {
squashed =
MutableIndexSegment::full(self.commit_id_length, self.change_id_length);
break;
}
let mut base_parent_file = None;
for parent_file in self.as_composite().ancestor_files_without_local() {
// TODO: We should probably also squash if the parent file has less than N
// commits, regardless of how many (few) are in `self`.
if 2 * num_new_commits < parent_file.segment_num_commits() {
base_parent_file = Some(parent_file.clone());
break;
}
num_new_commits += parent_file.segment_num_commits();
files_to_squash.push(parent_file.clone());
}
if files_to_squash.is_empty() {
return self;
}
let mut squashed = if let Some(parent_file) = base_parent_file {
MutableIndexSegment::incremental(parent_file)
} else {
MutableIndexSegment::full(self.commit_id_length, self.change_id_length)
};
for parent_file in files_to_squash.iter().rev() {
squashed.add_commits_from(parent_file.as_ref());
}