From 5fbbaff982eb1753dcd24cf8573ee9838b849d6a Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 20 Aug 2026 19:25:40 +0200 Subject: [PATCH] Build applied patches from the focused diff Applying and reverse-applying custom patches must keep their staging, dirty-worktree, and conflict behavior after the patch-building panel is removed. Select the source lines in commit diffs while retaining every assertion about the resulting working tree and conflict resolution. Co-Authored-By: GitHub Copilot --- .../apply_custom_patch.go} | 22 +++++----- .../apply_custom_patch_in_reverse.go} | 22 +++++----- ..._custom_patch_in_reverse_with_conflict.go} | 42 +++++++++---------- .../apply_custom_patch_with_modified_file.go} | 21 ++++++---- ...stom_patch_with_modified_file_conflict.go} | 19 ++++++--- pkg/integration/tests/test_list.go | 10 ++--- 6 files changed, 73 insertions(+), 63 deletions(-) rename pkg/integration/tests/{patch_building/apply.go => main_view/apply_custom_patch.go} (73%) rename pkg/integration/tests/{patch_building/apply_in_reverse.go => main_view/apply_custom_patch_in_reverse.go} (67%) rename pkg/integration/tests/{patch_building/apply_in_reverse_with_conflict.go => main_view/apply_custom_patch_in_reverse_with_conflict.go} (69%) rename pkg/integration/tests/{patch_building/apply_with_modified_file_no_conflict.go => main_view/apply_custom_patch_with_modified_file.go} (75%) rename pkg/integration/tests/{patch_building/apply_with_modified_file_conflict.go => main_view/apply_custom_patch_with_modified_file_conflict.go} (78%) diff --git a/pkg/integration/tests/patch_building/apply.go b/pkg/integration/tests/main_view/apply_custom_patch.go similarity index 73% rename from pkg/integration/tests/patch_building/apply.go rename to pkg/integration/tests/main_view/apply_custom_patch.go index 8ecb34fe4..ac8ba523a 100644 --- a/pkg/integration/tests/patch_building/apply.go +++ b/pkg/integration/tests/main_view/apply_custom_patch.go @@ -1,15 +1,17 @@ -package patch_building +package main_view import ( "github.com/jesseduffield/lazygit/pkg/config" . "github.com/jesseduffield/lazygit/pkg/integration/components" ) -var Apply = NewIntegrationTest(NewIntegrationTestArgs{ - Description: "Apply a custom patch", +var ApplyCustomPatch = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Apply a custom patch built from a branch commit's focused diff", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Gui.UseHunkModeInStagingView = false + }, SetupRepo: func(shell *Shell) { shell.NewBranch("branch-a") shell.CreateFileAndAdd("file1", "first line\n") @@ -18,7 +20,6 @@ var Apply = NewIntegrationTest(NewIntegrationTestArgs{ shell.NewBranch("branch-b") shell.UpdateFileAndAdd("file1", "first line\nsecond line\n") shell.Commit("update") - shell.Checkout("branch-a") }, Run: func(t *TestDriver, keys config.KeybindingConfig) { @@ -44,12 +45,15 @@ var Apply = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Contains("M file1").IsSelected(), ). + Press(keys.Universal.FocusMainView) + + t.Views().Main(). + IsFocused(). + SelectedLines(Contains("+second line")). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) - t.Views().Secondary().Content(Contains("second line")) - t.Common().SelectPatchOption(MatchesRegexp(`Apply patch$`)) t.Views().Files(). @@ -57,8 +61,6 @@ var Apply = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Contains("file1").IsSelected(), ) - - t.Views().Secondary(). - Content(Contains("second line")) + t.Views().Secondary().Content(Contains("second line")) }, }) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse.go b/pkg/integration/tests/main_view/apply_custom_patch_in_reverse.go similarity index 67% rename from pkg/integration/tests/patch_building/apply_in_reverse.go rename to pkg/integration/tests/main_view/apply_custom_patch_in_reverse.go index 485ac9f02..6625d81ba 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse.go +++ b/pkg/integration/tests/main_view/apply_custom_patch_in_reverse.go @@ -1,15 +1,17 @@ -package patch_building +package main_view import ( "github.com/jesseduffield/lazygit/pkg/config" . "github.com/jesseduffield/lazygit/pkg/integration/components" ) -var ApplyInReverse = NewIntegrationTest(NewIntegrationTestArgs{ - Description: "Apply a custom patch in reverse", +var ApplyCustomPatchInReverse = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Apply a custom patch built from a focused commit diff in reverse", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Gui.UseHunkModeInStagingView = false + }, SetupRepo: func(shell *Shell) { shell.CreateFileAndAdd("file1", "file1 content\n") shell.CreateFileAndAdd("file2", "file2 content\n") @@ -30,13 +32,15 @@ var ApplyInReverse = NewIntegrationTest(NewIntegrationTestArgs{ Equals(" A file1"), Equals(" A file2"), ). - SelectNextItem(). + Press(keys.Universal.FocusMainView) + + t.Views().Main(). + IsFocused(). + SelectedLines(Contains("+file1 content")). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) - t.Views().Secondary().Content(Contains("+file1 content")) - t.Common().SelectPatchOption(Contains("Apply patch in reverse")) t.Views().Files(). @@ -44,8 +48,6 @@ var ApplyInReverse = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Contains("D").Contains("file1").IsSelected(), ) - - t.Views().Secondary(). - Content(Contains("-file1 content")) + t.Views().Secondary().Content(Contains("-file1 content")) }, }) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go b/pkg/integration/tests/main_view/apply_custom_patch_in_reverse_with_conflict.go similarity index 69% rename from pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go rename to pkg/integration/tests/main_view/apply_custom_patch_in_reverse_with_conflict.go index 5b02510b8..db1c901b3 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go +++ b/pkg/integration/tests/main_view/apply_custom_patch_in_reverse_with_conflict.go @@ -1,15 +1,17 @@ -package patch_building +package main_view import ( "github.com/jesseduffield/lazygit/pkg/config" . "github.com/jesseduffield/lazygit/pkg/integration/components" ) -var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ - Description: "Apply a custom patch in reverse, resulting in a conflict", +var ApplyCustomPatchInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Apply a multi-file custom patch in reverse when one file conflicts", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Gui.UseHunkModeInStagingView = false + }, SetupRepo: func(shell *Shell) { shell.CreateFileAndAdd("file1", "file1 content\n") shell.CreateFileAndAdd("file2", "file2 content\n") @@ -38,21 +40,17 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ Equals(" M file1"), Equals(" M file2"), ). - SelectNextItem(). - // Add both files to the patch; the first will conflict, the second won't - PressPrimaryAction(). - Tap(func() { - t.Views().Information().Content(Contains("Building patch")) + Press(keys.Universal.FocusMainView) - t.Views().Secondary().Content( - Contains("+more file1 content")) - }). - SelectNextItem(). + t.Views().Main(). + IsFocused(). + SelectedLines(Contains("+more file1 content")). + Press(keys.Universal.ToggleRangeSelect). + NavigateToLine(Contains("+more file2 content")). PressPrimaryAction() - t.Views().Secondary().Content( - Contains("+more file1 content").Contains("+more file2 content")) - + t.Views().Information().Content(Contains("Building patch")) + t.Views().Secondary().Content(Contains("+more file1 content").Contains("+more file2 content")) t.Common().SelectPatchOption(Contains("Apply patch in reverse")) t.ExpectPopup().Alert(). @@ -87,12 +85,10 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ Equals(" M file1").IsSelected(), Equals(" M file2"), ) - - t.Views().Secondary(). - ContainsLines( - Contains(" file1 content"), - Contains("-more file1 content"), - Contains("-even more file1"), - ) + t.Views().Secondary().ContainsLines( + Contains(" file1 content"), + Contains("-more file1 content"), + Contains("-even more file1"), + ) }, }) diff --git a/pkg/integration/tests/patch_building/apply_with_modified_file_no_conflict.go b/pkg/integration/tests/main_view/apply_custom_patch_with_modified_file.go similarity index 75% rename from pkg/integration/tests/patch_building/apply_with_modified_file_no_conflict.go rename to pkg/integration/tests/main_view/apply_custom_patch_with_modified_file.go index 5f8ff1006..3b8a9b1c8 100644 --- a/pkg/integration/tests/patch_building/apply_with_modified_file_no_conflict.go +++ b/pkg/integration/tests/main_view/apply_custom_patch_with_modified_file.go @@ -1,15 +1,17 @@ -package patch_building +package main_view import ( "github.com/jesseduffield/lazygit/pkg/config" . "github.com/jesseduffield/lazygit/pkg/integration/components" ) -var ApplyWithModifiedFileNoConflict = NewIntegrationTest(NewIntegrationTestArgs{ - Description: "Apply a custom patch, with a modified file in the working tree that does not conflict with the patch", +var ApplyCustomPatchWithModifiedFile = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Apply a custom patch alongside a non-conflicting working-tree change", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Gui.UseHunkModeInStagingView = false + }, SetupRepo: func(shell *Shell) { shell.NewBranch("branch-a") shell.CreateFileAndAdd("file1", "1\n2\n3\n") @@ -45,12 +47,15 @@ var ApplyWithModifiedFileNoConflict = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Equals("M file1").IsSelected(), ). + Press(keys.Universal.FocusMainView) + + t.Views().Main(). + IsFocused(). + SelectedLines(Contains("+4")). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) - t.Views().Secondary().Content(Contains("3\n+4")) - t.Common().SelectPatchOption(MatchesRegexp(`Apply patch$`)) t.ExpectPopup().Confirmation().Title(Equals("Must stage files")). @@ -62,8 +67,6 @@ var ApplyWithModifiedFileNoConflict = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Equals("M file1").IsSelected(), ) - - t.Views().Secondary(). - Content(Contains("-1\n+11\n 2\n 3\n+4")) + t.Views().Secondary().Content(Contains("-1\n+11\n 2\n 3\n+4")) }, }) diff --git a/pkg/integration/tests/patch_building/apply_with_modified_file_conflict.go b/pkg/integration/tests/main_view/apply_custom_patch_with_modified_file_conflict.go similarity index 78% rename from pkg/integration/tests/patch_building/apply_with_modified_file_conflict.go rename to pkg/integration/tests/main_view/apply_custom_patch_with_modified_file_conflict.go index 5b529ad70..6b00e4d43 100644 --- a/pkg/integration/tests/patch_building/apply_with_modified_file_conflict.go +++ b/pkg/integration/tests/main_view/apply_custom_patch_with_modified_file_conflict.go @@ -1,15 +1,17 @@ -package patch_building +package main_view import ( "github.com/jesseduffield/lazygit/pkg/config" . "github.com/jesseduffield/lazygit/pkg/integration/components" ) -var ApplyWithModifiedFileConflict = NewIntegrationTest(NewIntegrationTestArgs{ - Description: "Apply a custom patch, with a modified file in the working tree that conflicts with the patch", +var ApplyCustomPatchWithModifiedFileConflict = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Apply a custom patch that conflicts with a working-tree change", ExtraCmdArgs: []string{}, Skip: false, - SetupConfig: func(config *config.AppConfig) {}, + SetupConfig: func(config *config.AppConfig) { + config.GetUserConfig().Gui.UseHunkModeInStagingView = false + }, SetupRepo: func(shell *Shell) { shell.NewBranch("branch-a") shell.CreateFileAndAdd("file1", "1\n2\n3\n") @@ -45,12 +47,17 @@ var ApplyWithModifiedFileConflict = NewIntegrationTest(NewIntegrationTestArgs{ Lines( Equals("M file1").IsSelected(), ). + Press(keys.Universal.FocusMainView) + + t.Views().Main(). + IsFocused(). + SelectedLines(Contains("-1")). + Press(keys.Universal.ToggleRangeSelect). + Press(keys.Universal.NextItem). PressPrimaryAction() t.Views().Information().Content(Contains("Building patch")) - t.Views().Secondary().Content(Contains("-1\n+11\n")) - t.Common().SelectPatchOption(MatchesRegexp(`Apply patch$`)) t.ExpectPopup().Confirmation().Title(Equals("Must stage files")). diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index 69702325f..00644310c 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -367,6 +367,11 @@ var tests = []*components.IntegrationTest{ interactive_rebase.SwapWithConflict, interactive_rebase.ViewFilesOfTodoEntries, main_view.AdvanceAfterStagingShiftsLineNumbers, + main_view.ApplyCustomPatch, + main_view.ApplyCustomPatchInReverse, + main_view.ApplyCustomPatchInReverseWithConflict, + main_view.ApplyCustomPatchWithModifiedFile, + main_view.ApplyCustomPatchWithModifiedFileConflict, main_view.BuildPatchFromACommitsDiff, main_view.BuildPatchFromAReflogEntry, main_view.BuildPatchFromAWholeCommitsDiff, @@ -484,11 +489,6 @@ var tests = []*components.IntegrationTest{ misc.RecentReposReftableRepo, misc.RecentReposWithLongNames, misc.StartInGitDir, - patch_building.Apply, - patch_building.ApplyInReverse, - patch_building.ApplyInReverseWithConflict, - patch_building.ApplyWithModifiedFileConflict, - patch_building.ApplyWithModifiedFileNoConflict, patch_building.CopyRenamedFileDiff, patch_building.RemoveFromCommit, patch_building.RemovePartsOfAddedFile,