repo: extract add_heads() that can import commits from multiple heads

This allows us to reorder commits to be indexed in bulk.

The incremental update optimization is applied only for a single head. This
could be tried for multiple heads, but it's unlikely that every head has
a single new commit for each.
This commit is contained in:
Yuya Nishihara 2023-08-12 09:11:31 +09:00
parent 157a0e748b
commit 73a4b7f5bf

View file

@ -16,12 +16,12 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::fs;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::ops::Deref; use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::{fs, slice};
use itertools::Itertools; use itertools::Itertools;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@ -915,23 +915,31 @@ impl MutableRepo {
} }
pub fn add_head(&mut self, head: &Commit) { pub fn add_head(&mut self, head: &Commit) {
self.add_heads(slice::from_ref(head));
}
pub fn add_heads(&mut self, heads: &[Commit]) {
let current_heads = self.view.get_mut().heads(); let current_heads = self.view.get_mut().heads();
// Use incremental update for common case of adding a single commit on top a // Use incremental update for common case of adding a single commit on top a
// current head. TODO: Also use incremental update when adding a single // current head. TODO: Also use incremental update when adding a single
// commit on top a non-head. // commit on top a non-head.
match heads {
[] => {}
[head]
if head if head
.parent_ids() .parent_ids()
.iter() .iter()
.all(|parent_id| current_heads.contains(parent_id)) .all(|parent_id| current_heads.contains(parent_id)) =>
{ {
self.index.add_commit(head); self.index.add_commit(head);
self.view.get_mut().add_head(head.id()); self.view.get_mut().add_head(head.id());
for parent_id in head.parent_ids() { for parent_id in head.parent_ids() {
self.view.get_mut().remove_head(parent_id); self.view.get_mut().remove_head(parent_id);
} }
} else { }
_ => {
let missing_commits = dag_walk::topo_order_forward( let missing_commits = dag_walk::topo_order_forward(
vec![head.clone()], heads.iter().cloned(),
|commit: &Commit| commit.id().clone(), |commit: &Commit| commit.id().clone(),
|commit: &Commit| -> Vec<Commit> { |commit: &Commit| -> Vec<Commit> {
commit commit
@ -945,10 +953,13 @@ impl MutableRepo {
for missing_commit in &missing_commits { for missing_commit in &missing_commits {
self.index.add_commit(missing_commit); self.index.add_commit(missing_commit);
} }
for head in heads {
self.view.get_mut().add_head(head.id()); self.view.get_mut().add_head(head.id());
}
self.view.mark_dirty(); self.view.mark_dirty();
} }
} }
}
pub fn remove_head(&mut self, head: &CommitId) { pub fn remove_head(&mut self, head: &CommitId) {
self.view_mut().remove_head(head); self.view_mut().remove_head(head);