index: extract a function for adding all commits from a segment

I also restructured the loop in `maybe_squash_with_ancestors()` to
hopefully make it a little clearer.
This commit is contained in:
Martin von Zweigbergk 2021-03-06 10:37:57 -08:00
parent 3fc35288c0
commit d1509ffdd4

View file

@ -403,6 +403,30 @@ impl MutableIndex {
self.graph.push(entry);
}
fn add_commits_from(&mut self, other_segment: &dyn IndexSegment) {
let other = CompositeIndex(other_segment);
for pos in other_segment.segment_num_parent_commits()..other.num_commits() {
let entry = other.entry_by_pos(pos);
let parent_ids: Vec<_> = entry
.parent_positions()
.iter()
.map(|pos| other.entry_by_pos(*pos).commit_id())
.collect();
let predecessor_ids: Vec<_> = entry
.predecessor_positions()
.iter()
.map(|pos| other.entry_by_pos(*pos).commit_id())
.collect();
self.add_commit_data(
entry.commit_id(),
entry.change_id(),
entry.is_pruned(),
parent_ids,
predecessor_ids,
);
}
}
fn serialize(self) -> Vec<u8> {
assert_eq!(self.graph.len(), self.lookup.len());
@ -498,50 +522,38 @@ impl MutableIndex {
/// return MutableIndex with the commits from both. This is done
/// recursively, so the stack of index files has O(log n) files.
fn maybe_squash_with_ancestors(self) -> MutableIndex {
if self.parent_file.is_none() {
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 num_new_commits < parent_file.segment_num_commits() {
squashed = MutableIndex::incremental(parent_file);
break;
}
num_new_commits += parent_file.segment_num_commits();
files_to_squash.push(parent_file.clone());
maybe_parent_file = parent_file.parent_file.clone();
}
None => {
squashed = MutableIndex::full(self.hash_length);
break;
}
}
}
if files_to_squash.is_empty() {
return self;
}
let mut num_new_commits = self.segment_num_commits();
let mut parent_file = self.parent_file.as_ref().unwrap().clone();
let mut squashed;
loop {
// TODO: We should probably also squash if the parent file has less than N
// commits, regardless of how many (few) are in `self`.
if num_new_commits < parent_file.segment_num_commits() {
squashed = MutableIndex::incremental(parent_file);
break;
}
if parent_file.parent_file.is_none() {
squashed = MutableIndex::full(self.hash_length);
break;
}
num_new_commits += parent_file.segment_num_commits();
parent_file = parent_file.parent_file.as_ref().unwrap().clone();
}
// TODO: This can be made more efficient by walking the parent files in order
// and not looking up via `self`.
for pos in squashed.num_parent_commits..self.num_commits() {
let entry = self.entry_by_pos(pos);
let parent_ids: Vec<_> = entry
.parent_positions()
.iter()
.map(|pos| self.entry_by_pos(*pos).commit_id())
.collect();
let predecessor_ids: Vec<_> = entry
.predecessor_positions()
.iter()
.map(|pos| self.entry_by_pos(*pos).commit_id())
.collect();
squashed.add_commit_data(
entry.commit_id(),
entry.change_id(),
entry.is_pruned(),
parent_ids,
predecessor_ids,
);
for parent_file in files_to_squash.iter().rev() {
squashed.add_commits_from(parent_file.as_ref());
}
squashed.add_commits_from(&self);
squashed
}