From 899e25b208a7867506b0c38702b15ea32e62e587 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 12 Jun 2024 11:17:39 +0200 Subject: [PATCH 1/2] Show "exec" todos in the list of rebase todos Unfortunately it isn't possible to delete them. This would often be useful, but our todo rewriting mechanisms rely on being able to find todos by some identifier (hash for pick, ref for update-ref), and exec todos don't have a unique identifier. --- pkg/commands/git_commands/commit_loader.go | 2 + .../controllers/local_commits_controller.go | 3 + pkg/i18n/english.go | 2 + .../interactive_rebase/show_exec_todos.go | 57 +++++++++++++++++++ pkg/integration/tests/test_list.go | 1 + 5 files changed, 65 insertions(+) create mode 100644 pkg/integration/tests/interactive_rebase/show_exec_todos.go diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index f116ded1f..f9cfff141 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -344,6 +344,8 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*mod for _, t := range todos { if t.Command == todo.UpdateRef { t.Msg = t.Ref + } else if t.Command == todo.Exec { + t.Msg = t.ExecCommand } else if t.Commit == "" { // Command does not have a commit associated, skip continue diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index f8717f413..de5116b74 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -284,6 +284,9 @@ func (self *LocalCommitsController) GetOnRenderToMain() func() error { map[string]string{ "ref": strings.TrimPrefix(commit.Name, "refs/heads/"), })) + } else if commit.Action == todo.Exec { + task = types.NewRenderStringTask( + self.c.Tr.ExecCommandHere + "\n\n" + commit.Name) } else { cmdObj := self.c.Git().Commit.ShowCmdObj(commit.Hash, self.c.Modes().Filtering.GetPath()) task = types.NewRunPtyTask(cmdObj.GetCmd()) diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index d32aafbf2..7aabbbc2b 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -164,6 +164,7 @@ type TranslationSet struct { RewordCommitEditor string NoCommitsThisBranch string UpdateRefHere string + ExecCommandHere string Error string Undo string UndoReflog string @@ -1093,6 +1094,7 @@ func EnglishTranslationSet() TranslationSet { SquashTooltip: "Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it.", NoCommitsThisBranch: "No commits for this branch", UpdateRefHere: "Update branch '{{.ref}}' here", + ExecCommandHere: "Execute the following command here:", CannotSquashOrFixupFirstCommit: "There's no commit below to squash into", Fixup: "Fixup", SureFixupThisCommit: "Are you sure you want to 'fixup' the selected commit(s) into the commit below?", diff --git a/pkg/integration/tests/interactive_rebase/show_exec_todos.go b/pkg/integration/tests/interactive_rebase/show_exec_todos.go new file mode 100644 index 000000000..bf10737e4 --- /dev/null +++ b/pkg/integration/tests/interactive_rebase/show_exec_todos.go @@ -0,0 +1,57 @@ +package interactive_rebase + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var ShowExecTodos = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Show exec todos in the rebase todo list", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(cfg *config.AppConfig) { + cfg.UserConfig.CustomCommands = []config.CustomCommand{ + { + Key: "X", + Context: "commits", + Command: "git -c core.editor=: rebase -i -x false HEAD^^", + }, + } + }, + SetupRepo: func(shell *Shell) { + shell. + NewBranch("branch1"). + CreateNCommits(3) + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Press("X"). + Tap(func() { + t.ExpectPopup().Alert().Title(Equals("Error")).Content(Contains("Rebasing (2/4)Executing: false")).Confirm() + }). + Lines( + Contains("exec").Contains("false"), + Contains("pick").Contains("CI commit 03"), + Contains("CI ◯ <-- YOU ARE HERE --- commit 02"), + Contains("CI ◯ commit 01"), + ). + Tap(func() { + t.Common().ContinueRebase() + t.ExpectPopup().Alert().Title(Equals("Error")).Content(Contains("Rebasing (4/4)Executing: false")).Confirm() + }). + Lines( + Contains("CI ◯ <-- YOU ARE HERE --- commit 03"), + Contains("CI ◯ commit 02"), + Contains("CI ◯ commit 01"), + ). + Tap(func() { + t.Common().ContinueRebase() + }). + Lines( + Contains("CI ◯ commit 03"), + Contains("CI ◯ commit 02"), + Contains("CI ◯ commit 01"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index ea2b93f45..5fbbfb4e2 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -209,6 +209,7 @@ var tests = []*components.IntegrationTest{ interactive_rebase.RewordLastCommit, interactive_rebase.RewordYouAreHereCommit, interactive_rebase.RewordYouAreHereCommitWithEditor, + interactive_rebase.ShowExecTodos, interactive_rebase.SquashDownFirstCommit, interactive_rebase.SquashDownSecondCommit, interactive_rebase.SquashFixupsAbove, From 92dd80c3e3af0c399261272889cc21c5efaaac08 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 12 Jun 2024 12:13:07 +0200 Subject: [PATCH 2/2] Suspend lazygit when continuing a rebase with exec todos It's likely that the exec todos are some kind of lengthy build task whose output the user will want to see in the terminal. --- .../helpers/merge_and_rebase_helper.go | 21 ++++++++++++++++++- .../interactive_rebase/show_exec_todos.go | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index c2aa1418a..c5ad78c47 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -9,10 +9,12 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/git_commands" + "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/samber/lo" + "github.com/stefanhaller/git-todo-parser/todo" ) type MergeAndRebaseHelper struct { @@ -110,7 +112,12 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { // we should end up with a command like 'git merge --continue' // it's impossible for a rebase to require a commit so we'll use a subprocess only if it's a merge - if status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && self.c.UserConfig.Git.Merging.ManualCommit { + needsSubprocess := (status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && self.c.UserConfig.Git.Merging.ManualCommit) || + // but we'll also use a subprocess if we have exec todos; those are likely to be lengthy build + // tasks whose output the user will want to see in the terminal + (status == enums.REBASE_MODE_REBASING && command != REBASE_OPTION_ABORT && self.hasExecTodos()) + + if needsSubprocess { // TODO: see if we should be calling more of the code from self.Git.Rebase.GenericMergeOrRebaseAction return self.c.RunSubprocessAndRefresh( self.c.Git().Rebase.GenericMergeOrRebaseActionCmdObj(commandType, command), @@ -123,6 +130,18 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { return nil } +func (self *MergeAndRebaseHelper) hasExecTodos() bool { + for _, commit := range self.c.Model().Commits { + if commit.Status != models.StatusRebasing { + break + } + if commit.Action == todo.Exec { + return true + } + } + return false +} + var conflictStrings = []string{ "Failed to merge in the changes", "When you have resolved this problem", diff --git a/pkg/integration/tests/interactive_rebase/show_exec_todos.go b/pkg/integration/tests/interactive_rebase/show_exec_todos.go index bf10737e4..b66036d02 100644 --- a/pkg/integration/tests/interactive_rebase/show_exec_todos.go +++ b/pkg/integration/tests/interactive_rebase/show_exec_todos.go @@ -38,7 +38,7 @@ var ShowExecTodos = NewIntegrationTest(NewIntegrationTestArgs{ ). Tap(func() { t.Common().ContinueRebase() - t.ExpectPopup().Alert().Title(Equals("Error")).Content(Contains("Rebasing (4/4)Executing: false")).Confirm() + t.ExpectPopup().Alert().Title(Equals("Error")).Content(Contains("exit status 1")).Confirm() }). Lines( Contains("CI ◯ <-- YOU ARE HERE --- commit 03"),