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

git: simplify import_head() as it doesn't have to process multiple head commits

This commit is contained in:
Yuya Nishihara 2024-01-25 18:27:03 +09:00
parent fc114ef217
commit 8a67191d25
2 changed files with 28 additions and 40 deletions

View file

@ -516,51 +516,35 @@ pub fn import_head(mut_repo: &mut MutableRepo) -> Result<(), GitImportError> {
let git_repo = git_backend.git_repo(); let git_repo = git_backend.git_repo();
let old_git_head = mut_repo.view().git_head(); let old_git_head = mut_repo.view().git_head();
let changed_git_head = if let Ok(head_git_commit) = git_repo.head_commit() { let new_git_head_id = if let Ok(oid) = git_repo.head_id() {
let head_commit_id = CommitId::from_bytes(head_git_commit.id().as_bytes()); Some(CommitId::from_bytes(oid.as_bytes()))
let new_head_target = RefTarget::normal(head_commit_id);
(*old_git_head != new_head_target).then_some(new_head_target)
} else { } else {
old_git_head.is_present().then(RefTarget::absent) None
}; };
if old_git_head.as_resolved() == Some(&new_git_head_id) {
return Ok(());
}
// Bulk-import all reachable Git commits to the backend to reduce overhead of // Import new head
// table merging and ref updates. if let Some(head_id) = &new_git_head_id {
let index = mut_repo.index(); let index = mut_repo.index();
let missing_head_ids = changed_git_head if !index.has_id(head_id) {
.iter() git_backend.import_head_commits([head_id]).map_err(|err| {
.flat_map(|target| target.added_ids()) GitImportError::MissingHeadTarget {
.filter(|&id| !index.has_id(id)); id: head_id.clone(),
let heads_imported = git_backend.import_head_commits(missing_head_ids).is_ok(); err,
}
// Import new remote heads
let mut head_commits = Vec::new();
let get_commit = |id| {
// If bulk-import failed, try again to find bad head or ref.
if !heads_imported && !index.has_id(id) {
git_backend.import_head_commits([id])?;
}
store.get_commit(id)
};
if let Some(new_head_target) = &changed_git_head {
for id in new_head_target.added_ids() {
let commit = get_commit(id).map_err(|err| GitImportError::MissingHeadTarget {
id: id.clone(),
err,
})?; })?;
head_commits.push(commit);
} }
// It's unlikely the imported commits were missing, but I/O-related
// error can still occur.
store
.get_commit(head_id)
.and_then(|commit| mut_repo.add_head(&commit))
.map_err(GitImportError::InternalBackend)?;
} }
// It's unlikely the imported commits were missing, but I/O-related error
// can still occur.
mut_repo
.add_heads(&head_commits)
.map_err(GitImportError::InternalBackend)?;
// Apply the change that happened in git since last time we imported refs. mut_repo.set_git_head_target(RefTarget::resolved(new_git_head_id));
if let Some(new_head_target) = changed_git_head {
mut_repo.set_git_head_target(new_head_target);
}
Ok(()) Ok(())
} }

View file

@ -107,10 +107,14 @@ impl RefTarget {
RefTarget { merge } RefTarget { merge }
} }
/// Returns the underlying value if this target is non-conflicting.
pub fn as_resolved(&self) -> Option<&Option<CommitId>> {
self.merge.as_resolved()
}
/// Returns id if this target is non-conflicting and points to a commit. /// Returns id if this target is non-conflicting and points to a commit.
pub fn as_normal(&self) -> Option<&CommitId> { pub fn as_normal(&self) -> Option<&CommitId> {
let maybe_id = self.merge.as_resolved()?; self.as_resolved()?.as_ref()
maybe_id.as_ref()
} }
/// Returns true if this target points to no commit. /// Returns true if this target points to no commit.