diff --git a/lib/src/default_index/composite.rs b/lib/src/default_index/composite.rs index 943a084c4d..67903921c6 100644 --- a/lib/src/default_index/composite.rs +++ b/lib/src/default_index/composite.rs @@ -91,12 +91,16 @@ impl<'a> CompositeIndex<'a> { CompositeIndex(segment) } - fn ancestor_files_without_local(&self) -> impl Iterator> { + /// Iterates parent and its ancestor readonly index segments. + pub(super) fn ancestor_files_without_local( + &self, + ) -> impl Iterator> { let parent_file = self.0.segment_parent_file(); iter::successors(parent_file, |file| file.segment_parent_file()) } - fn ancestor_index_segments(&self) -> impl Iterator { + /// Iterates self and its ancestor index segments. + pub(super) fn ancestor_index_segments(&self) -> impl Iterator { iter::once(self.0).chain( self.ancestor_files_without_local() .map(|file| file.as_ref() as &dyn IndexSegment), diff --git a/lib/src/default_index/mutable.rs b/lib/src/default_index/mutable.rs index 3b45036f07..7260225ebd 100644 --- a/lib/src/default_index/mutable.rs +++ b/lib/src/default_index/mutable.rs @@ -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()); } @@ -279,11 +273,10 @@ impl MutableIndexSegment { return Ok(self.parent_file.unwrap()); } - let squashed = self.maybe_squash_with_ancestors(); let mut buf = Vec::new(); - squashed.serialize_parent_filename(&mut buf); + self.serialize_parent_filename(&mut buf); let local_entries_offset = buf.len(); - squashed.serialize_local_entries(&mut buf); + self.serialize_local_entries(&mut buf); let mut hasher = Blake2b512::new(); hasher.update(&buf); let index_file_id_hex = hex::encode(hasher.finalize()); @@ -297,9 +290,9 @@ impl MutableIndexSegment { Ok(ReadonlyIndexSegment::load_with_parent_file( &mut &buf[local_entries_offset..], index_file_id_hex, - squashed.parent_file, - squashed.commit_id_length, - squashed.change_id_length, + self.parent_file, + self.commit_id_length, + self.change_id_length, ) .expect("in-memory index data should be valid and readable")) } @@ -411,8 +404,8 @@ impl DefaultMutableIndex { self.0.add_commit_data(commit_id, change_id, parent_ids); } - pub(super) fn save_in(self, dir: &Path) -> io::Result> { - self.0.save_in(dir) + pub(super) fn squash_and_save_in(self, dir: &Path) -> io::Result> { + self.0.maybe_squash_with_ancestors().save_in(dir) } } diff --git a/lib/src/default_index/store.rs b/lib/src/default_index/store.rs index 4c59d709c5..0d188a2c12 100644 --- a/lib/src/default_index/store.rs +++ b/lib/src/default_index/store.rs @@ -194,7 +194,7 @@ impl DefaultIndexStore { op_id: &OperationId, ) -> Result, DefaultIndexStoreError> { let index_segment = mutable_index - .save_in(&self.dir) + .squash_and_save_in(&self.dir) .map_err(DefaultIndexStoreError::SaveIndex)?; self.associate_file_with_operation(&index_segment, op_id) .map_err(|source| DefaultIndexStoreError::AssociateIndex {