diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index dc95c00df..f3ae211a5 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -48,6 +48,11 @@ func (self *CustomPatchOptionsMenuAction) Call() error { } if self.c.Git().Patch.PatchBuilder.CanRebase && self.c.Git().Status.WorkingTreeState().None() { + var disabledReasonForMergeCommit *types.DisabledReason + if self.isPatchFromMergeCommit() { + disabledReasonForMergeCommit = &types.DisabledReason{Text: self.c.Tr.NotSupportedForPatchFromMergeCommit} + } + menuItems = append(menuItems, []*types.MenuItem{ { Label: fmt.Sprintf(self.c.Tr.RemovePatchFromOriginalCommit, utils.ShortHash(self.c.Git().Patch.PatchBuilder.To)), @@ -68,10 +73,11 @@ func (self *CustomPatchOptionsMenuAction) Call() error { Keys: menuKey('n'), }, { - Label: self.c.Tr.MovePatchIntoNewCommitBefore, - Tooltip: self.c.Tr.MovePatchIntoNewCommitBeforeTooltip, - OnPress: self.handlePullPatchIntoNewCommitBefore, - Keys: menuKey('N'), + Label: self.c.Tr.MovePatchIntoNewCommitBefore, + Tooltip: self.c.Tr.MovePatchIntoNewCommitBeforeTooltip, + OnPress: self.handlePullPatchIntoNewCommitBefore, + Keys: menuKey('N'), + DisabledReason: disabledReasonForMergeCommit, }, }...) @@ -79,7 +85,10 @@ func (self *CustomPatchOptionsMenuAction) Call() error { selectedCommit := self.c.Contexts().LocalCommits.GetSelected() if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Hash() { - var disabledReason *types.DisabledReason + disabledReason := disabledReasonForMergeCommit + if selectedCommit.IsMerge() { + disabledReason = &types.DisabledReason{Text: self.c.Tr.CannotMovePatchToMergeCommit} + } if self.c.Contexts().LocalCommits.AreMultipleItemsSelected() { disabledReason = &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported} } @@ -123,6 +132,11 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int { return -1 } +func (self *CustomPatchOptionsMenuAction) isPatchFromMergeCommit() bool { + commitIndex := self.getPatchCommitIndex() + return commitIndex != -1 && self.c.Model().Commits[commitIndex].IsMerge() +} + func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error { commits := self.c.Model().Commits commitIndex := self.getPatchCommitIndex() diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 0c8ed7d74..05a74b0fe 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -1013,6 +1013,8 @@ type TranslationSet struct { RangeSelectUp string RangeSelectDown string RangeSelectNotSupported string + NotSupportedForPatchFromMergeCommit string + CannotMovePatchToMergeCommit string NoItemSelected string SelectedItemIsNotABranch string SelectedItemDoesNotHaveFiles string @@ -2230,6 +2232,8 @@ func EnglishTranslationSet() *TranslationSet { RangeSelectUp: "Range select up", RangeSelectDown: "Range select down", RangeSelectNotSupported: "Action does not support range selection, please select a single item", + NotSupportedForPatchFromMergeCommit: "Not supported for a patch from a merge commit", + CannotMovePatchToMergeCommit: "Cannot move a patch to a merge commit", NoItemSelected: "No item selected", SelectedItemIsNotABranch: "Selected item is not a branch", SelectedItemDoesNotHaveFiles: "Selected item does not have files to view", diff --git a/pkg/integration/tests/main_view/disable_moving_patch_from_merge_commit.go b/pkg/integration/tests/main_view/disable_moving_patch_from_merge_commit.go new file mode 100644 index 000000000..59cf687a9 --- /dev/null +++ b/pkg/integration/tests/main_view/disable_moving_patch_from_merge_commit.go @@ -0,0 +1,60 @@ +package main_view + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var DisableMovingPatchFromMergeCommit = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Moving a patch from a merge commit to another commit, or into a new commit before it, is disabled", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell. + NewBranch("main-branch"). + CreateFileAndAdd("file1", "file1 content\n"). + Commit("first commit"). + NewBranch("feature"). + CreateFileAndAdd("file2", "file2 content\n"). + Commit("feature commit"). + Checkout("main-branch"). + CreateFileAndAdd("file3", "file3 content\n"). + Commit("main commit"). + Merge("feature") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("Merge branch 'feature' into main-branch").IsSelected(), + Contains("feature commit"), + Contains("main commit"), + Contains("first commit"), + ). + PressEnter() + + t.Views().CommitFiles(). + IsFocused(). + Lines( + Contains("file2").IsSelected(), + ). + PressPrimaryAction() + + t.Views().Information().Content(Contains("Building patch")) + + t.Views().Commits(). + Focus(). + NavigateToLine(Contains("first commit")) + + t.GlobalPress(keys.Universal.CreatePatchOptionsMenu) + + t.ExpectPopup().Menu(). + Title(Equals("Patch options")). + Select(Contains("Move patch to selected commit")). + Tooltip(Contains("Disabled: Not supported for a patch from a merge commit")). + Select(Contains("Move patch into new commit before the original commit")). + Tooltip(Contains("Disabled: Not supported for a patch from a merge commit")). + Cancel() + }, +}) diff --git a/pkg/integration/tests/main_view/disable_moving_patch_to_merge_commit.go b/pkg/integration/tests/main_view/disable_moving_patch_to_merge_commit.go new file mode 100644 index 000000000..aebeec9ac --- /dev/null +++ b/pkg/integration/tests/main_view/disable_moving_patch_to_merge_commit.go @@ -0,0 +1,71 @@ +package main_view + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var DisableMovingPatchToMergeCommit = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Moving a patch to an earlier or later merge commit is disabled", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell. + NewBranch("main-branch"). + CreateFileAndAdd("file1", "file1 content\n"). + Commit("first commit"). + NewBranch("feature"). + CreateFileAndAdd("file2", "file2 content\n"). + Commit("feature commit"). + Checkout("main-branch"). + CreateFileAndAdd("file3", "file3 content\n"). + Commit("main commit"). + Merge("feature"). + CreateFileAndAdd("file4", "file4 content\n"). + Commit("top commit") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + checkMovingPatchToMergeCommitIsDisabled := func(commitToMoveFrom string, file string) { + t.Views().Commits(). + Focus(). + NavigateToLine(Contains(commitToMoveFrom)). + PressEnter() + + t.Views().CommitFiles(). + IsFocused(). + Lines( + Contains(file).IsSelected(), + ). + PressPrimaryAction() + + t.Views().Information().Content(Contains("Building patch")) + + t.Views().Commits(). + Focus(). + NavigateToLine(Contains("Merge branch 'feature' into main-branch")) + + t.GlobalPress(keys.Universal.CreatePatchOptionsMenu) + + t.ExpectPopup().Menu(). + Title(Equals("Patch options")). + Select(Contains("Move patch to selected commit")). + Tooltip(Contains("Disabled: Cannot move a patch to a merge commit")). + Cancel() + + t.Common().ResetCustomPatch() + } + + t.Views().Commits(). + Lines( + Contains("top commit").IsSelected(), + Contains("Merge branch 'feature' into main-branch"), + Contains("feature commit"), + Contains("main commit"), + Contains("first commit"), + ) + + checkMovingPatchToMergeCommitIsDisabled("top commit", "file4") + checkMovingPatchToMergeCommitIsDisabled("main commit", "file3") + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 13282ef5d..559816011 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -407,6 +407,8 @@ var tests = []*components.IntegrationTest{ main_view.CopySelectedDiffLines, main_view.CustomPatchGoesThroughTheDiffRenderer, main_view.CustomPatchIgnoresLineEndingConversion, + main_view.DisableMovingPatchFromMergeCommit, + main_view.DisableMovingPatchToMergeCommit, main_view.DiscardAllChanges, main_view.DiscardDiffLines, main_view.DiscardFromACommitOnlyWhereItCanBeRewritten,