refactor integrate_upstream_commits_for_series

This commit is contained in:
Kiril Videlov 2024-10-16 22:09:59 +02:00
parent a2506177f1
commit 6a056f9ad7
No known key found for this signature in database
GPG Key ID: A4C733025427C471

View File

@ -6,7 +6,7 @@ use gitbutler_repo::{
LogUntil, RepositoryExt as _,
};
use gitbutler_stack::StackId;
use gitbutler_stack_api::{commit_by_oid_or_change_id, StackExt};
use gitbutler_stack_api::{commit_by_oid_or_change_id, Series, StackExt};
use crate::{
branch_trees::{
@ -34,28 +34,59 @@ pub fn integrate_upstream_commits_for_series(
"No remote has been configured for the target branch"
))?;
let series = all_series
let subject_series = all_series
.iter()
.find(|series| series.head.name == series_name)
.ok_or(anyhow!("Series not found"))?;
let upstream_reference = series.head.remote_reference(remote.as_str())?;
let upstream_reference = subject_series.head.remote_reference(remote.as_str())?;
let remote_head = repo.find_reference(&upstream_reference)?.peel_to_commit()?;
let stack_merge_base = repo.merge_base(branch.head(), default_target.sha)?;
let upstream_to_local_merge_base = repo.merge_base(branch.head(), remote_head.id())?;
let new_stack_head = new_stack_head(
repo,
branch.allow_rebasing,
branch.head(),
remote_head.id(),
default_target.sha,
all_series.clone(),
subject_series,
)?;
// Find what the new head and branch tree should be
let BranchHeadAndTree { head, tree } =
compute_updated_branch_head_for_commits(repo, branch.head(), branch.tree, new_stack_head)?;
let mut branch = branch.clone();
branch.set_stack_head(ctx, head, Some(tree))?;
checkout_branch_trees(ctx, perm)?;
crate::integration::update_workspace_commit(&vb_state, ctx)?;
Ok(())
}
fn new_stack_head(
repo: &git2::Repository,
allow_rebasing: bool,
branch_head: git2::Oid,
remote_head: git2::Oid,
target_head: git2::Oid,
all_series: Vec<Series>,
subject_series: &Series,
) -> Result<git2::Oid> {
let stack_merge_base = repo.merge_base(branch_head, target_head)?;
let upstream_to_local_merge_base = repo.merge_base(branch_head, remote_head)?;
// Rebasing will be performed if configured.
// If the series to integrate is not the latest one, it will also do a rebase.
let new_stack_head = if branch.allow_rebasing || Some(series) != all_series.first() {
let new_stack_head = if allow_rebasing || Some(subject_series) != all_series.first() {
// commits to rebase
let mut ordered_commits_to_rebase = vec![];
for series in all_series.clone() {
// if this is the series that is getting the upstream commits, they are added first
if series.head.name == series_name {
if series.head.name == subject_series.head.name {
for id in series.upstream_only_commits.iter() {
let commit = commit_by_oid_or_change_id(
id,
repo,
remote_head.id(),
remote_head,
upstream_to_local_merge_base,
)?;
ordered_commits_to_rebase.push(commit.id());
@ -63,7 +94,7 @@ pub fn integrate_upstream_commits_for_series(
}
// now add the existing local commits to the rebase list
for id in series.local_commits.iter() {
let commit = commit_by_oid_or_change_id(id, repo, branch.head(), stack_merge_base)?;
let commit = commit_by_oid_or_change_id(id, repo, branch_head, stack_merge_base)?;
ordered_commits_to_rebase.push(commit.id());
}
}
@ -75,34 +106,25 @@ pub fn integrate_upstream_commits_for_series(
} else {
// If rebase is not allowed AND this is the latest series - create a merge commit on top
let series_head_commit = commit_by_oid_or_change_id(
&series.head.target,
&subject_series.head.target,
repo,
branch.head(),
branch_head,
upstream_to_local_merge_base,
)?;
let remote_head_commit = repo.find_commit(remote_head)?;
let merge_commit = gitbutler_merge_commits(
repo,
series_head_commit,
remote_head.clone(),
&series.head.name, // for error messages only
&series
remote_head_commit,
&subject_series.head.name, // for error messages only
&subject_series
.head
.remote_reference(&default_target.sha.to_string())?, // for error messages only
.remote_reference(&target_head.to_string())?, // for error messages only
)?;
// the new merge commit is now the stack and series head
merge_commit.id()
};
// Find what the new head and branch tree should be
let BranchHeadAndTree { head, tree } =
compute_updated_branch_head_for_commits(repo, branch.head(), branch.tree, new_stack_head)?;
let mut branch = branch.clone();
branch.set_stack_head(ctx, head, Some(tree))?;
checkout_branch_trees(ctx, perm)?;
crate::integration::update_workspace_commit(&vb_state, ctx)?;
Ok(())
Ok(new_stack_head)
}
/// Integrates upstream work from a remote branch.