From 3d4f1657d1780828ff693d562cf98ed1501ce4d9 Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Mon, 28 Oct 2024 16:10:28 +0100 Subject: [PATCH] Fix - prevent pushing of already integrated branches when in a stack --- crates/gitbutler-branch-actions/src/stack.rs | 23 ++++++++++++++++--- .../gitbutler-branch-actions/src/virtual.rs | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/gitbutler-branch-actions/src/stack.rs b/crates/gitbutler-branch-actions/src/stack.rs index 00a37abd19..0b24f1d52f 100644 --- a/crates/gitbutler-branch-actions/src/stack.rs +++ b/crates/gitbutler-branch-actions/src/stack.rs @@ -6,7 +6,7 @@ use gitbutler_commit::commit_ext::CommitExt; use gitbutler_patch_reference::{CommitOrChangeId, PatchReference}; use gitbutler_project::Project; use gitbutler_repo_actions::RepoActionsExt; -use gitbutler_stack::PatchReferenceUpdate; +use gitbutler_stack::{PatchReferenceUpdate, Series}; use gitbutler_stack::{Stack, StackId, Target}; use serde::{Deserialize, Serialize}; @@ -130,20 +130,27 @@ pub fn push_stack(project: &Project, branch_id: StackId, with_force: bool) -> Re let stack = state.get_branch(branch_id)?; let repo = ctx.repository(); - let merge_base = - repo.find_commit(repo.merge_base(stack.head(), state.get_default_target()?.sha)?)?; + let default_target = state.get_default_target()?; + let merge_base = repo.find_commit(repo.merge_base(stack.head(), default_target.sha)?)?; let merge_base = if let Some(change_id) = merge_base.change_id() { CommitOrChangeId::ChangeId(change_id) } else { CommitOrChangeId::CommitId(merge_base.id().to_string()) }; + // First fetch, because we dont want to push integrated series + ctx.fetch(&default_target.push_remote_name(), None)?; + let check_commit = IsCommitIntegrated::new(ctx, &default_target)?; let stack_series = stack.list_series(ctx)?; for series in stack_series { if series.head.target == merge_base { // Nothing to push for this one continue; } + if series_integrated(&check_commit, &series)? { + // Already integrated, nothing to push + continue; + } let push_details = stack.push_details(ctx, series.head.name)?; ctx.push( push_details.head, @@ -156,6 +163,16 @@ pub fn push_stack(project: &Project, branch_id: StackId, with_force: bool) -> Re Ok(()) } +fn series_integrated(check_commit: &IsCommitIntegrated, series: &Series) -> Result { + let mut is_integrated = false; + for commit in series.clone().local_commits.iter().rev() { + if !is_integrated { + is_integrated = check_commit.is_integrated(commit)?; + } + } + Ok(is_integrated) +} + /// Returns the stack series for the API. /// Newest first, oldest last in the list pub(crate) fn stack_series( diff --git a/crates/gitbutler-branch-actions/src/virtual.rs b/crates/gitbutler-branch-actions/src/virtual.rs index 251a0ed168..b15c859e81 100644 --- a/crates/gitbutler-branch-actions/src/virtual.rs +++ b/crates/gitbutler-branch-actions/src/virtual.rs @@ -947,7 +947,7 @@ pub(crate) struct IsCommitIntegrated<'repo> { } impl<'repo> IsCommitIntegrated<'repo> { - fn new(ctx: &'repo CommandContext, target: &Target) -> anyhow::Result { + pub(crate) fn new(ctx: &'repo CommandContext, target: &Target) -> anyhow::Result { let remote_branch = ctx .repository() .maybe_find_branch_by_refname(&target.branch.clone().into())?