mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 02:26:14 +03:00
refactor integrate_upstream_commits_for_series
This commit is contained in:
parent
a2506177f1
commit
6a056f9ad7
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user