1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-19 12:12:42 +02:00

Show "exec" todos in the list of rebase todos (#3654)

- **PR Description**

It is sometimes useful to perform a `git rebase -x "make test"
origin/main` in order to verify that all commits of the current branch
are green. However, if the rebase stops in the middle because one of
those tests fail, it's easy to accidentally press `m <enter>` in lazygit
after amending some fix, not realizing that the rest of the tests will
now run invisibly inside lazygit.

This PR makes two changes to improve this situation:
- It shows exec todos in the commits panel: 
<img width="482" alt="image"
src="https://github.com/jesseduffield/lazygit/assets/1225667/608b24e8-9f3d-4a5f-9bb5-e16268c86e83">
- when continuing a rebase and there are exec todos, it suspends itself
to the background so that you can see the output of the test runs in the
terminal.

We can improve this further in the future; for example, it would often
be useful to be able to delete some of the exec commands, this is not
currently possible. But it's still better than before.
This commit is contained in:
Stefan Haller 2024-06-12 14:38:44 +02:00 committed by GitHub
commit c08a5fe4e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 85 additions and 1 deletions

View File

@ -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

View File

@ -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",

View File

@ -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())

View File

@ -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?",

View File

@ -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("exit status 1")).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"),
)
},
})

View File

@ -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,