diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 7e7d9354fe7..4aba9a7a845 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -136,7 +136,7 @@ func NewGitCommandAux( branchLoader := git_commands.NewBranchLoader(cmn, gitCommon, cmd, branchCommands.CurrentBranchInfo, configCommands) commitFileLoader := git_commands.NewCommitFileLoader(cmn, cmd) - commitLoader := git_commands.NewCommitLoader(cmn, cmd, statusCommands.RebaseMode, gitCommon) + commitLoader := git_commands.NewCommitLoader(cmn, cmd, statusCommands.WorkingTreeState, gitCommon) reflogCommitLoader := git_commands.NewReflogCommitLoader(cmn, cmd) remoteLoader := git_commands.NewRemoteLoader(cmn, cmd, repo.Remotes) worktreeLoader := git_commands.NewWorktreeLoader(gitCommon) diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index f9cfff1419e..22050b38472 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -13,7 +13,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/samber/lo" @@ -31,10 +30,10 @@ type CommitLoader struct { *common.Common cmd oscommands.ICmdObjBuilder - getRebaseMode func() (enums.RebaseMode, error) - readFile func(filename string) ([]byte, error) - walkFiles func(root string, fn filepath.WalkFunc) error - dotGitDir string + getWorkingTreeState func() models.WorkingTreeState + readFile func(filename string) ([]byte, error) + walkFiles func(root string, fn filepath.WalkFunc) error + dotGitDir string *GitCommon } @@ -42,16 +41,16 @@ type CommitLoader struct { func NewCommitLoader( cmn *common.Common, cmd oscommands.ICmdObjBuilder, - getRebaseMode func() (enums.RebaseMode, error), + getWorkingTreeState func() models.WorkingTreeState, gitCommon *GitCommon, ) *CommitLoader { return &CommitLoader{ - Common: cmn, - cmd: cmd, - getRebaseMode: getRebaseMode, - readFile: os.ReadFile, - walkFiles: filepath.Walk, - GitCommon: gitCommon, + Common: cmn, + cmd: cmd, + getWorkingTreeState: getWorkingTreeState, + readFile: os.ReadFile, + walkFiles: filepath.Walk, + GitCommon: gitCommon, } } @@ -172,17 +171,12 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod } } - rebaseMode, err := self.getRebaseMode() - if err != nil { - return nil, err - } - - if rebaseMode == enums.REBASE_MODE_NONE { + if !self.getWorkingTreeState().Rebasing { // not in rebase mode so return original commits return result, nil } - rebasingCommits, err := self.getHydratedRebasingCommits(rebaseMode) + rebasingCommits, err := self.getHydratedRebasingCommits() if err != nil { return nil, err } @@ -248,8 +242,8 @@ func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool } } -func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode) ([]*models.Commit, error) { - commits := self.getRebasingCommits(rebaseMode) +func (self *CommitLoader) getHydratedRebasingCommits() ([]*models.Commit, error) { + commits := self.getRebasingCommits() if len(commits) == 0 { return nil, nil @@ -310,11 +304,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode // git-rebase-todo example: // pick ac446ae94ee560bdb8d1d057278657b251aaef17 ac446ae // pick afb893148791a2fbd8091aeb81deba4930c73031 afb8931 -func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) []*models.Commit { - if rebaseMode != enums.REBASE_MODE_INTERACTIVE { - return nil - } - +func (self *CommitLoader) getRebasingCommits() []*models.Commit { bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo")) if err != nil { self.Log.Error(fmt.Sprintf("error occurred reading git-rebase-todo: %s", err.Error())) diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go index f9c4cdff6d2..f7b07513454 100644 --- a/pkg/commands/git_commands/commit_loader_test.go +++ b/pkg/commands/git_commands/commit_loader_test.go @@ -8,7 +8,6 @@ import ( "github.com/go-errors/errors" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/stefanhaller/git-todo-parser/todo" @@ -33,17 +32,15 @@ func TestGetCommits(t *testing.T) { expectedCommits []*models.Commit expectedError error logOrder string - rebaseMode enums.RebaseMode opts GetCommitsOptions mainBranches []string } scenarios := []scenario{ { - testName: "should return no commits if there are none", - logOrder: "topo-order", - rebaseMode: enums.REBASE_MODE_NONE, - opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, + testName: "should return no commits if there are none", + logOrder: "topo-order", + opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%m%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil), @@ -52,10 +49,9 @@ func TestGetCommits(t *testing.T) { expectedError: nil, }, { - testName: "should use proper upstream name for branch", - logOrder: "topo-order", - rebaseMode: enums.REBASE_MODE_NONE, - opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false}, + testName: "should use proper upstream name for branch", + logOrder: "topo-order", + opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false}, runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%m%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil), @@ -66,7 +62,6 @@ func TestGetCommits(t *testing.T) { { testName: "should return commits if they are present", logOrder: "topo-order", - rebaseMode: enums.REBASE_MODE_NONE, opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, mainBranches: []string{"master", "main", "develop"}, runner: oscommands.NewFakeRunner(t). @@ -203,7 +198,6 @@ func TestGetCommits(t *testing.T) { { testName: "should not call merge-base for mainBranches if none exist", logOrder: "topo-order", - rebaseMode: enums.REBASE_MODE_NONE, opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, mainBranches: []string{"master", "main"}, runner: oscommands.NewFakeRunner(t). @@ -240,7 +234,6 @@ func TestGetCommits(t *testing.T) { { testName: "should call merge-base for all main branches that exist", logOrder: "topo-order", - rebaseMode: enums.REBASE_MODE_NONE, opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, mainBranches: []string{"master", "main", "develop", "1.0-hotfixes"}, runner: oscommands.NewFakeRunner(t). @@ -277,10 +270,9 @@ func TestGetCommits(t *testing.T) { expectedError: nil, }, { - testName: "should not specify order if `log.order` is `default`", - logOrder: "default", - rebaseMode: enums.REBASE_MODE_NONE, - opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, + testName: "should not specify order if `log.order` is `default`", + logOrder: "default", + opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false}, runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%m%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil), @@ -289,10 +281,9 @@ func TestGetCommits(t *testing.T) { expectedError: nil, }, { - testName: "should set filter path", - logOrder: "default", - rebaseMode: enums.REBASE_MODE_NONE, - opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"}, + testName: "should set filter path", + logOrder: "default", + opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"}, runner: oscommands.NewFakeRunner(t). ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%m%x00%s", "--abbrev=40", "--follow", "--no-show-signature", "--", "src"}, "", nil), @@ -310,10 +301,10 @@ func TestGetCommits(t *testing.T) { cmd := oscommands.NewDummyCmdObjBuilder(scenario.runner) builder := &CommitLoader{ - Common: common, - cmd: cmd, - getRebaseMode: func() (enums.RebaseMode, error) { return scenario.rebaseMode, nil }, - dotGitDir: ".git", + Common: common, + cmd: cmd, + getWorkingTreeState: func() models.WorkingTreeState { return models.WorkingTreeState{} }, + dotGitDir: ".git", readFile: func(filename string) ([]byte, error) { return []byte(""), nil }, @@ -493,10 +484,10 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) { common := utils.NewDummyCommon() builder := &CommitLoader{ - Common: common, - cmd: oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)), - getRebaseMode: func() (enums.RebaseMode, error) { return enums.REBASE_MODE_INTERACTIVE, nil }, - dotGitDir: ".git", + Common: common, + cmd: oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)), + getWorkingTreeState: func() models.WorkingTreeState { return models.WorkingTreeState{Rebasing: true} }, + dotGitDir: ".git", readFile: func(filename string) ([]byte, error) { return []byte(""), nil }, diff --git a/pkg/commands/git_commands/patch.go b/pkg/commands/git_commands/patch.go index 36e094337c4..77563ab88bb 100644 --- a/pkg/commands/git_commands/patch.go +++ b/pkg/commands/git_commands/patch.go @@ -8,7 +8,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/app/daemon" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/patch" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/stefanhaller/git-todo-parser/todo" ) @@ -229,7 +228,7 @@ func (self *PatchCommands) MovePatchIntoIndex(commits []*models.Commit, commitId } if err := self.ApplyCustomPatch(true, true); err != nil { - if self.status.WorkingTreeState() == enums.REBASE_MODE_REBASING { + if self.status.WorkingTreeState().Rebasing { _ = self.rebase.AbortRebase() } return err @@ -253,7 +252,7 @@ func (self *PatchCommands) MovePatchIntoIndex(commits []*models.Commit, commitId self.rebase.onSuccessfulContinue = func() error { // add patches to index if err := self.ApplyPatch(patch, ApplyPatchOpts{Index: true, ThreeWay: true}); err != nil { - if self.status.WorkingTreeState() == enums.REBASE_MODE_REBASING { + if self.status.WorkingTreeState().Rebasing { _ = self.rebase.AbortRebase() } return err diff --git a/pkg/commands/git_commands/status.go b/pkg/commands/git_commands/status.go index 0e0ef37fcc5..ff09e22bc31 100644 --- a/pkg/commands/git_commands/status.go +++ b/pkg/commands/git_commands/status.go @@ -5,7 +5,7 @@ import ( "path/filepath" "strings" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" + "github.com/jesseduffield/lazygit/pkg/commands/models" ) type StatusCommands struct { @@ -20,50 +20,68 @@ func NewStatusCommands( } } -// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase -// and "interactive" for interactive rebase -func (self *StatusCommands) RebaseMode() (enums.RebaseMode, error) { - ok, err := self.IsInNormalRebase() - if err == nil && ok { - return enums.REBASE_MODE_NORMAL, nil - } - ok, err = self.IsInInteractiveRebase() - if err == nil && ok { - return enums.REBASE_MODE_INTERACTIVE, err - } - - return enums.REBASE_MODE_NONE, err -} - -func (self *StatusCommands) WorkingTreeState() enums.RebaseMode { - rebaseMode, _ := self.RebaseMode() - if rebaseMode != enums.REBASE_MODE_NONE { - return enums.REBASE_MODE_REBASING - } - merging, _ := self.IsInMergeState() - if merging { - return enums.REBASE_MODE_MERGING - } - return enums.REBASE_MODE_NONE +func (self *StatusCommands) WorkingTreeState() models.WorkingTreeState { + result := models.WorkingTreeState{} + result.Rebasing, _ = self.IsInRebase() + result.Merging, _ = self.IsInMergeState() + result.CherryPicking, _ = self.IsInCherryPick() + result.Reverting, _ = self.IsInRevert() + return result } func (self *StatusCommands) IsBareRepo() bool { return self.repoPaths.isBareRepo } -func (self *StatusCommands) IsInNormalRebase() (bool, error) { +func (self *StatusCommands) IsInRebase() (bool, error) { + exists, err := self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge")) + if err == nil && exists { + return true, nil + } return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply")) } -func (self *StatusCommands) IsInInteractiveRebase() (bool, error) { - return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge")) -} - // IsInMergeState states whether we are still mid-merge func (self *StatusCommands) IsInMergeState() (bool, error) { return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "MERGE_HEAD")) } +func (self *StatusCommands) IsInCherryPick() (bool, error) { + exists, err := self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "CHERRY_PICK_HEAD")) + if err != nil || !exists { + return exists, err + } + // Sometimes, CHERRY_PICK_HEAD is present during rebases even if no + // cherry-pick is in progress. I suppose this is because rebase used to be + // implemented as a series of cherry-picks, so this could be remnants of + // code that is shared between cherry-pick and rebase, or something. The way + // to tell if this is the case is to check for the presence of the + // stopped-sha file, which records the sha of the last pick that was + // executed before the rebase stopped, and seeing if the sha in that file is + // the same as the one in CHERRY_PICK_HEAD. + cherryPickHead, err := os.ReadFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "CHERRY_PICK_HEAD")) + if err != nil { + return false, err + } + stoppedSha, err := os.ReadFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge", "stopped-sha")) + if err != nil { + // If we get an error we assume the file doesn't exist + return true, nil + } + cherryPickHeadStr := strings.TrimSpace(string(cherryPickHead)) + stoppedShaStr := strings.TrimSpace(string(stoppedSha)) + // Need to use HasPrefix here because the cherry-pick HEAD is a full sha1, + // but stopped-sha is an abbreviated sha1 + if strings.HasPrefix(cherryPickHeadStr, stoppedShaStr) { + return false, nil + } + return true, nil +} + +func (self *StatusCommands) IsInRevert() (bool, error) { + return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "REVERT_HEAD")) +} + // Full ref (e.g. "refs/heads/mybranch") of the branch that is currently // being rebased, or empty string when we're not in a rebase func (self *StatusCommands) BranchBeingRebased() string { diff --git a/pkg/commands/models/working_tree_state.go b/pkg/commands/models/working_tree_state.go new file mode 100644 index 00000000000..3e7bdbf1b40 --- /dev/null +++ b/pkg/commands/models/working_tree_state.go @@ -0,0 +1,112 @@ +package models + +import "github.com/jesseduffield/lazygit/pkg/i18n" + +// The state of the working tree. Several of these can be true at once. +// In particular, the concrete multi-state combinations that can occur in +// practice are Rebasing+CherryPicking, and Rebasing+Reverting. Theoretically, I +// guess Rebasing+Merging could also happen, but it probably won't in practice. +type WorkingTreeState struct { + Rebasing bool + Merging bool + CherryPicking bool + Reverting bool +} + +func (self WorkingTreeState) Any() bool { + return self.Rebasing || self.Merging || self.CherryPicking || self.Reverting +} + +func (self WorkingTreeState) None() bool { + return !self.Any() +} + +type EffectiveWorkingTreeState int + +const ( + // this means we're neither rebasing nor merging, cherry-picking, or reverting + WORKING_TREE_STATE_NONE EffectiveWorkingTreeState = iota + WORKING_TREE_STATE_REBASING + WORKING_TREE_STATE_MERGING + WORKING_TREE_STATE_CHERRY_PICKING + WORKING_TREE_STATE_REVERTING +) + +// Effective returns the "current" state; if several states are true at once, +// this is the one that should be displayed in status views, and it's the one +// that the user can continue or abort. +// +// As an example, if you are stopped in an interactive rebase, and then you +// perform a cherry-pick, and the cherry-pick conflicts, then both +// WorkingTreeState.Rebasing and WorkingTreeState.CherryPicking are true. +// The effective state is cherry-picking, because that's the one you can +// continue or abort. It is not possible to continue the rebase without first +// aborting the cherry-pick. +func (self WorkingTreeState) Effective() EffectiveWorkingTreeState { + if self.Reverting { + return WORKING_TREE_STATE_REVERTING + } + if self.CherryPicking { + return WORKING_TREE_STATE_CHERRY_PICKING + } + if self.Merging { + return WORKING_TREE_STATE_MERGING + } + if self.Rebasing { + return WORKING_TREE_STATE_REBASING + } + return WORKING_TREE_STATE_NONE +} + +func (self WorkingTreeState) Title(tr *i18n.TranslationSet) string { + return map[EffectiveWorkingTreeState]string{ + WORKING_TREE_STATE_REBASING: tr.RebasingStatus, + WORKING_TREE_STATE_MERGING: tr.MergingStatus, + WORKING_TREE_STATE_CHERRY_PICKING: tr.CherryPickingStatus, + WORKING_TREE_STATE_REVERTING: tr.RevertingStatus, + }[self.Effective()] +} + +func (self WorkingTreeState) LowerCaseTitle(tr *i18n.TranslationSet) string { + return map[EffectiveWorkingTreeState]string{ + WORKING_TREE_STATE_REBASING: tr.LowercaseRebasingStatus, + WORKING_TREE_STATE_MERGING: tr.LowercaseMergingStatus, + WORKING_TREE_STATE_CHERRY_PICKING: tr.LowercaseCherryPickingStatus, + WORKING_TREE_STATE_REVERTING: tr.LowercaseRevertingStatus, + }[self.Effective()] +} + +func (self WorkingTreeState) OptionsMenuTitle(tr *i18n.TranslationSet) string { + return map[EffectiveWorkingTreeState]string{ + WORKING_TREE_STATE_REBASING: tr.RebaseOptionsTitle, + WORKING_TREE_STATE_MERGING: tr.MergeOptionsTitle, + WORKING_TREE_STATE_CHERRY_PICKING: tr.CherryPickOptionsTitle, + WORKING_TREE_STATE_REVERTING: tr.RevertOptionsTitle, + }[self.Effective()] +} + +func (self WorkingTreeState) OptionsMapTitle(tr *i18n.TranslationSet) string { + return map[EffectiveWorkingTreeState]string{ + WORKING_TREE_STATE_REBASING: tr.ViewRebaseOptions, + WORKING_TREE_STATE_MERGING: tr.ViewMergeOptions, + WORKING_TREE_STATE_CHERRY_PICKING: tr.ViewCherryPickOptions, + WORKING_TREE_STATE_REVERTING: tr.ViewRevertOptions, + }[self.Effective()] +} + +func (self WorkingTreeState) CommandName() string { + return map[EffectiveWorkingTreeState]string{ + WORKING_TREE_STATE_REBASING: "rebase", + WORKING_TREE_STATE_MERGING: "merge", + WORKING_TREE_STATE_CHERRY_PICKING: "cherry-pick", + WORKING_TREE_STATE_REVERTING: "revert", + }[self.Effective()] +} + +func (self WorkingTreeState) CanShowTodos() bool { + return self.Rebasing || self.CherryPicking || self.Reverting +} + +func (self WorkingTreeState) CanSkip() bool { + return self.Rebasing || self.CherryPicking || self.Reverting +} diff --git a/pkg/commands/types/enums/enums.go b/pkg/commands/types/enums/enums.go deleted file mode 100644 index 68a29d8f0ab..00000000000 --- a/pkg/commands/types/enums/enums.go +++ /dev/null @@ -1,22 +0,0 @@ -package enums - -type RebaseMode int - -const ( - // this means we're neither rebasing nor merging - REBASE_MODE_NONE RebaseMode = iota - // this means normal rebase as opposed to interactive rebase - REBASE_MODE_NORMAL - REBASE_MODE_INTERACTIVE - // REBASE_MODE_REBASING is a general state that captures both REBASE_MODE_NORMAL and REBASE_MODE_INTERACTIVE - REBASE_MODE_REBASING - REBASE_MODE_MERGING -) - -func (self RebaseMode) IsMerging() bool { - return self == REBASE_MODE_MERGING -} - -func (self RebaseMode) IsRebasing() bool { - return self == REBASE_MODE_INTERACTIVE || self == REBASE_MODE_NORMAL || self == REBASE_MODE_REBASING -} diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index 4f2f797e5da..f40f7f0ff49 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -7,7 +7,6 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/samber/lo" @@ -41,7 +40,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext { } } - showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING + showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh.CanShowTodos() hasRebaseUpdateRefsConfig := c.Git().Config.GetRebaseUpdateRefs() return presentation.GetCommitListDisplayStrings( diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index ced98b0725e..f231152db79 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -44,7 +43,7 @@ func (self *CustomPatchOptionsMenuAction) Call() error { }, } - if self.c.Git().Patch.PatchBuilder.CanRebase && self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_NONE { + if self.c.Git().Patch.PatchBuilder.CanRebase && self.c.Git().Status.WorkingTreeState().None() { menuItems = append(menuItems, []*types.MenuItem{ { Label: fmt.Sprintf(self.c.Tr.RemovePatchFromOriginalCommit, self.c.Git().Patch.PatchBuilder.To), @@ -115,7 +114,7 @@ func (self *CustomPatchOptionsMenuAction) getPatchCommitIndex() int { } func (self *CustomPatchOptionsMenuAction) validateNormalWorkingTreeState() (bool, error) { - if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE { + if self.c.Git().Status.WorkingTreeState().Any() { return false, errors.New(self.c.Tr.CantPatchWhileRebasingError) } return true, nil diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index 6fa6fefef9f..2d7f796a5cf 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -35,11 +35,12 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type OpensMenu: true, }, { - Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu), - Handler: opts.Guards.NoPopupPanel(self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu), - Description: self.c.Tr.ViewMergeRebaseOptions, - Tooltip: self.c.Tr.ViewMergeRebaseOptionsTooltip, - OpensMenu: true, + Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu), + Handler: opts.Guards.NoPopupPanel(self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu), + Description: self.c.Tr.ViewMergeRebaseOptions, + Tooltip: self.c.Tr.ViewMergeRebaseOptionsTooltip, + OpensMenu: true, + GetDisabledReason: self.canShowRebaseOptions, }, { Key: opts.GetKey(opts.Config.Universal.Refresh), @@ -191,3 +192,12 @@ func (self *GlobalController) escape() error { func (self *GlobalController) toggleWhitespace() error { return (&ToggleWhitespaceAction{c: self.c}).Call() } + +func (self *GlobalController) canShowRebaseOptions() *types.DisabledReason { + if self.c.Model().WorkingTreeStateAtLastCommitRefresh.None() { + return &types.DisabledReason{ + Text: self.c.Tr.NotMergingOrRebasing, + } + } + return nil +} diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go index 47108df166e..1cb2285d002 100644 --- a/pkg/gui/controllers/helpers/cherry_pick_helper.go +++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go @@ -77,7 +77,7 @@ func (self *CherryPickHelper) Paste() error { "numCommits": strconv.Itoa(len(self.getData().CherryPickedCommits)), }), HandleConfirm: func() error { - isInRebase, err := self.c.Git().Status.IsInInteractiveRebase() + isInRebase, err := self.c.Git().Status.IsInRebase() if err != nil { return err } @@ -107,7 +107,7 @@ func (self *CherryPickHelper) Paste() error { // be because there were conflicts. Don't clear the copied // commits in this case, since we might want to abort and // try pasting them again. - isInRebase, err = self.c.Git().Status.IsInInteractiveRebase() + isInRebase, err = self.c.Git().Status.IsInRebase() if err != nil { return err } diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index fba0b9014c8..3f2ced17e5c 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -10,7 +10,6 @@ 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" @@ -51,7 +50,7 @@ func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error { {option: REBASE_OPTION_ABORT, key: 'a'}, } - if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_REBASING { + if self.c.Git().Status.WorkingTreeState().CanSkip() { options = append(options, optionAndKey{ option: REBASE_OPTION_SKIP, key: 's', }) @@ -67,13 +66,7 @@ func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error { } }) - var title string - if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_MERGING { - title = self.c.Tr.MergeOptionsTitle - } else { - title = self.c.Tr.RebaseOptionsTitle - } - + title := self.c.Git().Status.WorkingTreeState().OptionsMenuTitle(self.c.Tr) return self.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems}) } @@ -84,12 +77,13 @@ func (self *MergeAndRebaseHelper) ContinueRebase() error { func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { status := self.c.Git().Status.WorkingTreeState() - if status != enums.REBASE_MODE_MERGING && status != enums.REBASE_MODE_REBASING { + if status.None() { return errors.New(self.c.Tr.NotMergingOrRebasing) } self.c.LogAction(fmt.Sprintf("Merge/Rebase: %s", command)) - if status == enums.REBASE_MODE_REBASING { + effectiveStatus := status.Effective() + if effectiveStatus == models.WORKING_TREE_STATE_REBASING { todoFile, err := os.ReadFile( filepath.Join(self.c.Git().RepoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"), ) @@ -103,23 +97,15 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { } } - commandType := "" - switch status { - case enums.REBASE_MODE_MERGING: - commandType = "merge" - case enums.REBASE_MODE_REBASING: - commandType = "rebase" - default: - // shouldn't be possible to land here - } + commandType := status.CommandName() // 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 - needsSubprocess := (status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && self.c.UserConfig().Git.Merging.ManualCommit) || + needsSubprocess := (effectiveStatus == models.WORKING_TREE_STATE_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()) + (effectiveStatus == models.WORKING_TREE_STATE_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 @@ -152,6 +138,8 @@ var conflictStrings = []string{ "fix conflicts", "Resolve all conflicts manually", "Merge conflict in file", + "hint: after resolving the conflicts", + "CONFLICT (content):", } func isMergeConflictErr(errStr string) bool { @@ -199,7 +187,7 @@ func (self *MergeAndRebaseHelper) CheckForConflicts(result error) error { } func (self *MergeAndRebaseHelper) PromptForConflictHandling() error { - mode := self.workingTreeStateNoun() + mode := self.c.Git().Status.WorkingTreeState().CommandName() return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.FoundConflictsTitle, Items: []*types.MenuItem{ @@ -224,7 +212,7 @@ func (self *MergeAndRebaseHelper) PromptForConflictHandling() error { func (self *MergeAndRebaseHelper) AbortMergeOrRebaseWithConfirm() error { // prompt user to confirm that they want to abort, then do it - mode := self.workingTreeStateNoun() + mode := self.c.Git().Status.WorkingTreeState().CommandName() self.c.Confirm(types.ConfirmOpts{ Title: fmt.Sprintf(self.c.Tr.AbortTitle, mode), Prompt: fmt.Sprintf(self.c.Tr.AbortPrompt, mode), @@ -236,23 +224,11 @@ func (self *MergeAndRebaseHelper) AbortMergeOrRebaseWithConfirm() error { return nil } -func (self *MergeAndRebaseHelper) workingTreeStateNoun() string { - workingTreeState := self.c.Git().Status.WorkingTreeState() - switch workingTreeState { - case enums.REBASE_MODE_NONE: - return "" - case enums.REBASE_MODE_MERGING: - return "merge" - default: - return "rebase" - } -} - // PromptToContinueRebase asks the user if they want to continue the rebase/merge that's in progress func (self *MergeAndRebaseHelper) PromptToContinueRebase() error { self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.Continue, - Prompt: self.c.Tr.ConflictsResolved, + Prompt: fmt.Sprintf(self.c.Tr.ConflictsResolved, self.c.Git().Status.WorkingTreeState().CommandName()), HandleConfirm: func() error { // By the time we get here, we might have unstaged changes again, // e.g. if the user had to fix build errors after resolving the diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go index 5798621552f..8c6b46eb662 100644 --- a/pkg/gui/controllers/helpers/mode_helper.go +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -4,8 +4,6 @@ import ( "fmt" "strings" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" - "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/samber/lo" @@ -116,12 +114,12 @@ func (self *ModeHelper) Statuses() []ModeStatus { }, { IsActive: func() bool { - return !self.suppressRebasingMode && self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE + return !self.suppressRebasingMode && self.c.Git().Status.WorkingTreeState().Any() }, Description: func() string { workingTreeState := self.c.Git().Status.WorkingTreeState() return self.withResetButton( - presentation.FormatWorkingTreeStateTitle(self.c.Tr, workingTreeState), style.FgYellow, + workingTreeState.Title(self.c.Tr), style.FgYellow, ) }, Reset: self.mergeAndRebaseHelper.AbortMergeOrRebaseWithConfirm, diff --git a/pkg/gui/controllers/helpers/patch_building_helper.go b/pkg/gui/controllers/helpers/patch_building_helper.go index 1cf64b3f8b4..73d0fb608b6 100644 --- a/pkg/gui/controllers/helpers/patch_building_helper.go +++ b/pkg/gui/controllers/helpers/patch_building_helper.go @@ -4,7 +4,6 @@ import ( "errors" "github.com/jesseduffield/lazygit/pkg/commands/patch" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/patch_exploring" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -22,7 +21,7 @@ func NewPatchBuildingHelper( } func (self *PatchBuildingHelper) ValidateNormalWorkingTreeState() (bool, error) { - if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE { + if self.c.Git().Status.WorkingTreeState().Any() { return false, errors.New(self.c.Tr.CantPatchWhileRebasingError) } return true, nil diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index 33347a363c7..93ad110f304 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -9,7 +9,6 @@ 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/context" "github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts" @@ -583,7 +582,7 @@ func (self *RefreshHelper) refreshStateFiles() error { } } - if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE && conflictFileCount == 0 && prevConflictFileCount > 0 { + if self.c.Git().Status.WorkingTreeState().Any() && conflictFileCount == 0 && prevConflictFileCount > 0 { self.c.OnUIThread(func() error { return self.mergeAndRebaseHelper.PromptToContinueRebase() }) } diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index 79e3a6549da..0b1b81e72af 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -8,7 +8,6 @@ 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/context" "github.com/jesseduffield/lazygit/pkg/gui/context/traits" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" @@ -682,7 +681,7 @@ func (self *LocalCommitsController) rewordEnabled(commit *models.Commit) *types. } func (self *LocalCommitsController) isRebasing() bool { - return self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE + return self.c.Model().WorkingTreeStateAtLastCommitRefresh.Any() } func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, startIdx int, endIdx int) error { @@ -869,7 +868,8 @@ func (self *LocalCommitsController) revert(commit *models.Commit) error { HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.RevertCommit) return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error { - if err := self.c.Git().Commit.Revert(commit.Hash); err != nil { + result := self.c.Git().Commit.Revert(commit.Hash) + if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(result); err != nil { return err } return self.afterRevertCommit() @@ -976,7 +976,7 @@ func (self *LocalCommitsController) moveFixupCommitToOwnerStackedBranch(targetCo return nil } - if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE { + if self.c.Git().Status.WorkingTreeState().Any() { // Can't move commits while rebasing return nil } diff --git a/pkg/gui/controllers/status_controller.go b/pkg/gui/controllers/status_controller.go index d517b870c85..8d173f46cf3 100644 --- a/pkg/gui/controllers/status_controller.go +++ b/pkg/gui/controllers/status_controller.go @@ -7,7 +7,6 @@ import ( "time" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/constants" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/style" @@ -109,19 +108,16 @@ func (self *StatusController) onClick(opts gocui.ViewMouseBindingOpts) error { upstreamStatus := utils.Decolorise(presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig())) repoName := self.c.Git().RepoPaths.RepoName() workingTreeState := self.c.Git().Status.WorkingTreeState() - switch workingTreeState { - case enums.REBASE_MODE_REBASING, enums.REBASE_MODE_MERGING: - workingTreeStatus := fmt.Sprintf("(%s)", presentation.FormatWorkingTreeStateLower(self.c.Tr, workingTreeState)) + if workingTreeState.Any() { + workingTreeStatus := fmt.Sprintf("(%s)", workingTreeState.LowerCaseTitle(self.c.Tr)) if cursorInSubstring(opts.X, upstreamStatus+" ", workingTreeStatus) { return self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu() } if cursorInSubstring(opts.X, upstreamStatus+" "+workingTreeStatus+" ", repoName) { return self.c.Helpers().Repos.CreateRecentReposMenu() } - default: - if cursorInSubstring(opts.X, upstreamStatus+" ", repoName) { - return self.c.Helpers().Repos.CreateRecentReposMenu() - } + } else if cursorInSubstring(opts.X, upstreamStatus+" ", repoName) { + return self.c.Helpers().Repos.CreateRecentReposMenu() } return nil diff --git a/pkg/gui/controllers/undo_controller.go b/pkg/gui/controllers/undo_controller.go index 198aa7d7bcb..9922f73d6b1 100644 --- a/pkg/gui/controllers/undo_controller.go +++ b/pkg/gui/controllers/undo_controller.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/jesseduffield/gocui" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -78,7 +77,7 @@ func (self *UndoController) reflogUndo() error { undoEnvVars := []string{"GIT_REFLOG_ACTION=[lazygit undo]"} undoingStatus := self.c.Tr.UndoingStatus - if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_REBASING { + if self.c.Git().Status.WorkingTreeState().Any() { return errors.New(self.c.Tr.CantUndoWhileRebasing) } @@ -142,7 +141,7 @@ func (self *UndoController) reflogRedo() error { redoEnvVars := []string{"GIT_REFLOG_ACTION=[lazygit redo]"} redoingStatus := self.c.Tr.RedoingStatus - if self.c.Git().Status.WorkingTreeState() == enums.REBASE_MODE_REBASING { + if self.c.Git().Status.WorkingTreeState().Any() { return errors.New(self.c.Tr.CantRedoWhileRebasing) } diff --git a/pkg/gui/options_map.go b/pkg/gui/options_map.go index 4f983655188..347db75898e 100644 --- a/pkg/gui/options_map.go +++ b/pkg/gui/options_map.go @@ -82,16 +82,10 @@ func (self *OptionsMapMgr) renderContextOptionsMap() { } // Mode-specific global keybindings - if self.c.Model().WorkingTreeStateAtLastCommitRefresh.IsRebasing() { + if state := self.c.Model().WorkingTreeStateAtLastCommitRefresh; state.Any() { optionsMap = utils.Prepend(optionsMap, bindingInfo{ key: keybindings.Label(self.c.KeybindingsOpts().Config.Universal.CreateRebaseOptionsMenu), - description: self.c.Tr.ViewRebaseOptions, - style: style.FgYellow, - }) - } else if self.c.Model().WorkingTreeStateAtLastCommitRefresh.IsMerging() { - optionsMap = utils.Prepend(optionsMap, bindingInfo{ - key: keybindings.Label(self.c.KeybindingsOpts().Config.Universal.CreateRebaseOptionsMenu), - description: self.c.Tr.ViewMergeOptions, + description: state.OptionsMapTitle(self.c.Tr), style: style.FgYellow, }) } diff --git a/pkg/gui/presentation/status.go b/pkg/gui/presentation/status.go index b3b2100673f..b636df6471d 100644 --- a/pkg/gui/presentation/status.go +++ b/pkg/gui/presentation/status.go @@ -5,7 +5,6 @@ import ( "time" "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/style" @@ -18,7 +17,7 @@ func FormatStatus( currentBranch *models.Branch, itemOperation types.ItemOperation, linkedWorktreeName string, - workingTreeState enums.RebaseMode, + workingTreeState models.WorkingTreeState, tr *i18n.TranslationSet, userConfig *config.UserConfig, ) string { @@ -31,8 +30,8 @@ func FormatStatus( } } - if workingTreeState != enums.REBASE_MODE_NONE { - status += style.FgYellow.Sprintf("(%s) ", FormatWorkingTreeStateLower(tr, workingTreeState)) + if workingTreeState.Any() { + status += style.FgYellow.Sprintf("(%s) ", workingTreeState.LowerCaseTitle(tr)) } name := GetBranchTextStyle(currentBranch.Name).Sprint(currentBranch.Name) diff --git a/pkg/gui/presentation/working_tree.go b/pkg/gui/presentation/working_tree.go deleted file mode 100644 index 1e1954bc985..00000000000 --- a/pkg/gui/presentation/working_tree.go +++ /dev/null @@ -1,30 +0,0 @@ -package presentation - -import ( - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" - "github.com/jesseduffield/lazygit/pkg/i18n" -) - -func FormatWorkingTreeStateTitle(tr *i18n.TranslationSet, rebaseMode enums.RebaseMode) string { - switch rebaseMode { - case enums.REBASE_MODE_REBASING: - return tr.RebasingStatus - case enums.REBASE_MODE_MERGING: - return tr.MergingStatus - default: - // should never actually display this - return "none" - } -} - -func FormatWorkingTreeStateLower(tr *i18n.TranslationSet, rebaseMode enums.RebaseMode) string { - switch rebaseMode { - case enums.REBASE_MODE_REBASING: - return tr.LowercaseRebasingStatus - case enums.REBASE_MODE_MERGING: - return tr.LowercaseMergingStatus - default: - // should never actually display this - return "none" - } -} diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 82a309fb113..e01c664230b 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -6,7 +6,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" - "github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/utils" @@ -288,7 +287,7 @@ type Model struct { ReflogCommits []*models.Commit BisectInfo *git_commands.BisectInfo - WorkingTreeStateAtLastCommitRefresh enums.RebaseMode + WorkingTreeStateAtLastCommitRefresh models.WorkingTreeState RemoteBranches []*models.RemoteBranch Tags []*models.Tag diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index b2deb7ab11f..aa413c6b5b0 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -306,11 +306,15 @@ type TranslationSet struct { ViewMergeRebaseOptionsTooltip string ViewMergeOptions string ViewRebaseOptions string + ViewCherryPickOptions string + ViewRevertOptions string NotMergingOrRebasing string AlreadyRebasing string RecentRepos string MergeOptionsTitle string RebaseOptionsTitle string + CherryPickOptionsTitle string + RevertOptionsTitle string CommitSummaryTitle string CommitDescriptionTitle string CommitDescriptionSubTitle string @@ -392,6 +396,8 @@ type TranslationSet struct { MergingStatus string LowercaseRebasingStatus string LowercaseMergingStatus string + LowercaseCherryPickingStatus string + LowercaseRevertingStatus string AmendingStatus string CherryPickingStatus string UndoingStatus string @@ -1359,11 +1365,15 @@ func EnglishTranslationSet() *TranslationSet { ViewMergeRebaseOptionsTooltip: "View options to abort/continue/skip the current merge/rebase.", ViewMergeOptions: "View merge options", ViewRebaseOptions: "View rebase options", + ViewCherryPickOptions: "View cherry-pick options", + ViewRevertOptions: "View revert options", NotMergingOrRebasing: "You are currently neither rebasing nor merging", AlreadyRebasing: "Can't perform this action during a rebase", RecentRepos: "Recent repositories", MergeOptionsTitle: "Merge options", RebaseOptionsTitle: "Rebase options", + CherryPickOptionsTitle: "Cherry-pick options", + RevertOptionsTitle: "Revert options", CommitSummaryTitle: "Commit summary", CommitDescriptionTitle: "Commit description", CommitDescriptionSubTitle: "Press {{.togglePanelKeyBinding}} to toggle focus, {{.commitMenuKeybinding}} to open menu", @@ -1381,7 +1391,7 @@ func EnglishTranslationSet() *TranslationSet { SecondaryTitle: "Secondary", ReflogCommitsTitle: "Reflog", GlobalTitle: "Global keybindings", - ConflictsResolved: "All merge conflicts resolved. Continue?", + ConflictsResolved: "All merge conflicts resolved. Continue the %s?", Continue: "Continue", UnstagedFilesAfterConflictsResolved: "Files have been modified since conflicts were resolved. Auto-stage them and continue?", Keybindings: "Keybindings", @@ -1451,8 +1461,10 @@ func EnglishTranslationSet() *TranslationSet { MovingStatus: "Moving", RebasingStatus: "Rebasing", MergingStatus: "Merging", - LowercaseRebasingStatus: "rebasing", // lowercase because it shows up in parentheses - LowercaseMergingStatus: "merging", // lowercase because it shows up in parentheses + LowercaseRebasingStatus: "rebasing", // lowercase because it shows up in parentheses + LowercaseMergingStatus: "merging", // lowercase because it shows up in parentheses + LowercaseCherryPickingStatus: "cherry-picking", // lowercase because it shows up in parentheses + LowercaseRevertingStatus: "reverting", // lowercase because it shows up in parentheses AmendingStatus: "Amending", CherryPickingStatus: "Cherry-picking", UndoingStatus: "Undoing", diff --git a/pkg/integration/clients/injector/main.go b/pkg/integration/clients/injector/main.go index 1f4c845e83d..96a4fb1f084 100644 --- a/pkg/integration/clients/injector/main.go +++ b/pkg/integration/clients/injector/main.go @@ -31,7 +31,7 @@ func main() { integrationTest := getIntegrationTest() - if os.Getenv(components.WAIT_FOR_DEBUGGER_ENV_VAR) != "" { + if os.Getenv(components.WAIT_FOR_DEBUGGER_ENV_VAR) != "" && !daemon.InDaemonMode() { println("Waiting for debugger to attach...") for !isDebuggerAttached() { time.Sleep(time.Millisecond * 100) diff --git a/pkg/integration/components/common.go b/pkg/integration/components/common.go index 2033a9442e8..2d62e9ea3c9 100644 --- a/pkg/integration/components/common.go +++ b/pkg/integration/components/common.go @@ -1,5 +1,7 @@ package components +import "fmt" + // for running common actions type Common struct { t *TestDriver @@ -43,10 +45,10 @@ func (self *Common) AcknowledgeConflicts() { Confirm() } -func (self *Common) ContinueOnConflictsResolved() { +func (self *Common) ContinueOnConflictsResolved(command string) { self.t.ExpectPopup().Confirmation(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")). + Content(Contains(fmt.Sprintf("All merge conflicts resolved. Continue the %s?", command))). Confirm() } diff --git a/pkg/integration/tests/branch/rebase.go b/pkg/integration/tests/branch/rebase.go index c7dc028afa4..6bc2083c42a 100644 --- a/pkg/integration/tests/branch/rebase.go +++ b/pkg/integration/tests/branch/rebase.go @@ -48,7 +48,7 @@ var Rebase = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Rebasing")) - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Information().Content(DoesNotContain("Rebasing")) diff --git a/pkg/integration/tests/branch/rebase_and_drop.go b/pkg/integration/tests/branch/rebase_and_drop.go index 594ae485457..d6c655cf7e5 100644 --- a/pkg/integration/tests/branch/rebase_and_drop.go +++ b/pkg/integration/tests/branch/rebase_and_drop.go @@ -77,7 +77,7 @@ var RebaseAndDrop = NewIntegrationTest(NewIntegrationTestArgs{ IsFocused(). PressPrimaryAction() - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Information().Content(DoesNotContain("Rebasing")) diff --git a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go index 9cd42cd2ee9..2ae75dafbe6 100644 --- a/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go +++ b/pkg/integration/tests/branch/rebase_conflicts_fix_build_errors.go @@ -51,7 +51,7 @@ var RebaseConflictsFixBuildErrors = NewIntegrationTest(NewIntegrationTestArgs{ popup := t.ExpectPopup().Confirmation(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")) + Content(Contains("All merge conflicts resolved. Continue the rebase?")) // While the popup is showing, fix some build errors t.Shell().UpdateFile("file", "make it compile again") diff --git a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go index cd968adf820..2f001ebe448 100644 --- a/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go +++ b/pkg/integration/tests/cherry_pick/cherry_pick_conflicts.go @@ -69,7 +69,7 @@ var CherryPickConflicts = NewIntegrationTest(NewIntegrationTestArgs{ SelectNextItem(). PressPrimaryAction() - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Files().IsEmpty() diff --git a/pkg/integration/tests/commit/revert_with_conflict_single_commit.go b/pkg/integration/tests/commit/revert_with_conflict_single_commit.go new file mode 100644 index 00000000000..949bf4b3427 --- /dev/null +++ b/pkg/integration/tests/commit/revert_with_conflict_single_commit.go @@ -0,0 +1,80 @@ +package commit + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var RevertWithConflictSingleCommit = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Reverts a commit that conflicts", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.CreateFileAndAdd("myfile", "") + shell.Commit("add empty file") + shell.CreateFileAndAdd("myfile", "first line\n") + shell.Commit("add first line") + shell.UpdateFileAndAdd("myfile", "first line\nsecond line\n") + shell.Commit("add second line") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("CI ◯ add second line").IsSelected(), + Contains("CI ◯ add first line"), + Contains("CI ◯ add empty file"), + ). + SelectNextItem(). + Press(keys.Commits.RevertCommit). + Tap(func() { + t.ExpectPopup().Confirmation(). + Title(Equals("Revert commit")). + Content(MatchesRegexp(`Are you sure you want to revert \w+?`)). + Confirm() + t.ExpectPopup().Menu(). + Title(Equals("Conflicts!")). + Select(Contains("View conflicts")). + Confirm() + }). + Lines( + /* EXPECTED: + Proper display of revert commits is not implemented yet; we'll do this in the next PR + Contains("revert").Contains("CI <-- CONFLICT --- add first line"), + Contains("CI ◯ add second line"), + Contains("CI ◯ add first line"), + Contains("CI ◯ add empty file"), + ACTUAL: */ + Contains("CI ◯ <-- YOU ARE HERE --- add second line"), + Contains("CI ◯ add first line"), + Contains("CI ◯ add empty file"), + ) + + t.Views().Options().Content(Contains("View revert options: m")) + t.Views().Information().Content(Contains("Reverting (Reset)")) + + t.Views().Files().IsFocused(). + Lines( + Contains("UU myfile").IsSelected(), + ). + PressEnter() + + t.Views().MergeConflicts().IsFocused(). + SelectNextItem(). + PressPrimaryAction() + + t.ExpectPopup().Alert(). + Title(Equals("Continue")). + Content(Contains("All merge conflicts resolved. Continue the revert?")). + Confirm() + + t.Views().Commits(). + Lines( + Contains(`CI ◯ Revert "add first line"`), + Contains("CI ◯ add second line"), + Contains("CI ◯ add first line"), + Contains("CI ◯ add empty file"), + ) + }, +}) diff --git a/pkg/integration/tests/commit/shared.go b/pkg/integration/tests/commit/shared.go index 072cc8154dd..b6861f13565 100644 --- a/pkg/integration/tests/commit/shared.go +++ b/pkg/integration/tests/commit/shared.go @@ -61,7 +61,7 @@ func doTheRebaseForAmendTests(t *TestDriver, keys config.KeybindingConfig) { t.ExpectPopup().Confirmation(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")). + Content(Contains("All merge conflicts resolved. Continue the rebase?")). Cancel() } diff --git a/pkg/integration/tests/conflicts/resolve_externally.go b/pkg/integration/tests/conflicts/resolve_externally.go index a8d717351b2..ab045f23397 100644 --- a/pkg/integration/tests/conflicts/resolve_externally.go +++ b/pkg/integration/tests/conflicts/resolve_externally.go @@ -25,7 +25,7 @@ var ResolveExternally = NewIntegrationTest(NewIntegrationTestArgs{ }). Press(keys.Universal.Refresh) - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("merge") t.Views().Files(). IsEmpty() diff --git a/pkg/integration/tests/conflicts/resolve_multiple_files.go b/pkg/integration/tests/conflicts/resolve_multiple_files.go index 542a74d54b7..7dd88e02c50 100644 --- a/pkg/integration/tests/conflicts/resolve_multiple_files.go +++ b/pkg/integration/tests/conflicts/resolve_multiple_files.go @@ -51,6 +51,6 @@ var ResolveMultipleFiles = NewIntegrationTest(NewIntegrationTestArgs{ ). PressPrimaryAction() - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("merge") }, }) diff --git a/pkg/integration/tests/conflicts/resolve_without_trailing_lf.go b/pkg/integration/tests/conflicts/resolve_without_trailing_lf.go index 2af1eac5445..3deafb28852 100644 --- a/pkg/integration/tests/conflicts/resolve_without_trailing_lf.go +++ b/pkg/integration/tests/conflicts/resolve_without_trailing_lf.go @@ -43,7 +43,7 @@ var ResolveWithoutTrailingLf = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Alert(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")). + Content(Contains("All merge conflicts resolved. Continue the merge?")). Cancel() t.Views().Files(). diff --git a/pkg/integration/tests/file/discard_all_dir_changes.go b/pkg/integration/tests/file/discard_all_dir_changes.go index e0381853462..6caa3d51993 100644 --- a/pkg/integration/tests/file/discard_all_dir_changes.go +++ b/pkg/integration/tests/file/discard_all_dir_changes.go @@ -93,7 +93,7 @@ var DiscardAllDirChanges = NewIntegrationTest(NewIntegrationTestArgs{ Confirm() }). Tap(func() { - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("merge") t.ExpectPopup().Confirmation(). Title(Equals("Continue")). Content(Contains("Files have been modified since conflicts were resolved. Auto-stage them and continue?")). diff --git a/pkg/integration/tests/file/discard_various_changes.go b/pkg/integration/tests/file/discard_various_changes.go index 0cc188f6572..bc68fd218ec 100644 --- a/pkg/integration/tests/file/discard_various_changes.go +++ b/pkg/integration/tests/file/discard_various_changes.go @@ -53,7 +53,7 @@ var DiscardVariousChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Confirmation(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")). + Content(Contains("All merge conflicts resolved. Continue the merge?")). Cancel() discardOneByOne([]statusFile{ diff --git a/pkg/integration/tests/file/discard_various_changes_range_select.go b/pkg/integration/tests/file/discard_various_changes_range_select.go index 403ece7f74f..937c50114b8 100644 --- a/pkg/integration/tests/file/discard_various_changes_range_select.go +++ b/pkg/integration/tests/file/discard_various_changes_range_select.go @@ -40,7 +40,7 @@ var DiscardVariousChangesRangeSelect = NewIntegrationTest(NewIntegrationTestArgs t.ExpectPopup().Confirmation(). Title(Equals("Continue")). - Content(Contains("All merge conflicts resolved. Continue?")). + Content(Contains("All merge conflicts resolved. Continue the merge?")). Cancel() }). Lines( diff --git a/pkg/integration/tests/interactive_rebase/amend_commit_with_conflict.go b/pkg/integration/tests/interactive_rebase/amend_commit_with_conflict.go index 2226b519646..c20ab51e0f8 100644 --- a/pkg/integration/tests/interactive_rebase/amend_commit_with_conflict.go +++ b/pkg/integration/tests/interactive_rebase/amend_commit_with_conflict.go @@ -60,7 +60,7 @@ var AmendCommitWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ SelectNextItem(). PressPrimaryAction() // pick "4" - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Common().AcknowledgeConflicts() diff --git a/pkg/integration/tests/interactive_rebase/rebase_with_commit_that_becomes_empty.go b/pkg/integration/tests/interactive_rebase/rebase_with_commit_that_becomes_empty.go new file mode 100644 index 00000000000..e9b743856d0 --- /dev/null +++ b/pkg/integration/tests/interactive_rebase/rebase_with_commit_that_becomes_empty.go @@ -0,0 +1,45 @@ +package interactive_rebase + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var RebaseWithCommitThatBecomesEmpty = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Performs a rebase involving a commit that becomes empty during the rebase, and gets dropped.", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + // It is important that we create two separate commits for the two + // changes to the file, but only one commit for the same changes on our + // branch; otherwise, the commit would be discarded at the start of the + // rebase already. + shell.CreateFileAndAdd("file", "change 1\n") + shell.Commit("master change 1") + shell.UpdateFileAndAdd("file", "change 1\nchange 2\n") + shell.Commit("master change 2") + shell.NewBranchFrom("branch", "HEAD^^") + shell.CreateFileAndAdd("file", "change 1\nchange 2\n") + shell.Commit("branch change") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Branches(). + Focus(). + NavigateToLine(Contains("master")). + Press(keys.Branches.RebaseBranch) + + t.ExpectPopup().Menu(). + Title(Equals("Rebase 'branch'")). + Select(Contains("Simple rebase")). + Confirm() + + t.Views().Commits(). + Lines( + Contains("master change 2"), + Contains("master change 1"), + Contains("initial commit"), + ) + }, +}) diff --git a/pkg/integration/tests/interactive_rebase/shared.go b/pkg/integration/tests/interactive_rebase/shared.go index 2e42c7f76f3..f34cbd7e22c 100644 --- a/pkg/integration/tests/interactive_rebase/shared.go +++ b/pkg/integration/tests/interactive_rebase/shared.go @@ -33,7 +33,7 @@ func handleConflictsFromSwap(t *TestDriver) { SelectNextItem(). PressPrimaryAction() // pick "three" - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Common().AcknowledgeConflicts() @@ -56,7 +56,7 @@ func handleConflictsFromSwap(t *TestDriver) { SelectNextItem(). PressPrimaryAction() // pick "two" - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Commits(). Focus(). diff --git a/pkg/integration/tests/patch_building/move_to_earlier_commit_from_added_file.go b/pkg/integration/tests/patch_building/move_to_earlier_commit_from_added_file.go index 122be38842e..a619128faca 100644 --- a/pkg/integration/tests/patch_building/move_to_earlier_commit_from_added_file.go +++ b/pkg/integration/tests/patch_building/move_to_earlier_commit_from_added_file.go @@ -71,7 +71,7 @@ var MoveToEarlierCommitFromAddedFile = NewIntegrationTest(NewIntegrationTestArgs SelectNextItem(). PressPrimaryAction() // choose the version with all three lines - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Commits(). Focus(). diff --git a/pkg/integration/tests/patch_building/move_to_index_from_added_file_with_conflict.go b/pkg/integration/tests/patch_building/move_to_index_from_added_file_with_conflict.go index c7acfcd5021..177e76e04eb 100644 --- a/pkg/integration/tests/patch_building/move_to_index_from_added_file_with_conflict.go +++ b/pkg/integration/tests/patch_building/move_to_index_from_added_file_with_conflict.go @@ -67,7 +67,7 @@ var MoveToIndexFromAddedFileWithConflict = NewIntegrationTest(NewIntegrationTest SelectNextItem(). PressPrimaryAction() - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.ExpectPopup().Alert(). Title(Equals("Error")). diff --git a/pkg/integration/tests/patch_building/move_to_index_with_conflict.go b/pkg/integration/tests/patch_building/move_to_index_with_conflict.go index 51b6f4766f0..bdf0765d9ef 100644 --- a/pkg/integration/tests/patch_building/move_to_index_with_conflict.go +++ b/pkg/integration/tests/patch_building/move_to_index_with_conflict.go @@ -62,7 +62,7 @@ var MoveToIndexWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ ). PressPrimaryAction() - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.ExpectPopup().Alert(). Title(Equals("Error")). diff --git a/pkg/integration/tests/sync/pull_merge_conflict.go b/pkg/integration/tests/sync/pull_merge_conflict.go index 2161f6abd97..45ca39b1fbc 100644 --- a/pkg/integration/tests/sync/pull_merge_conflict.go +++ b/pkg/integration/tests/sync/pull_merge_conflict.go @@ -60,7 +60,7 @@ var PullMergeConflict = NewIntegrationTest(NewIntegrationTestArgs{ ). PressPrimaryAction() // choose 'content4' - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("merge") t.Views().Status().Content(Equals("↑2 repo → master")) diff --git a/pkg/integration/tests/sync/pull_rebase_conflict.go b/pkg/integration/tests/sync/pull_rebase_conflict.go index d9541e0edfa..1d41b2ac351 100644 --- a/pkg/integration/tests/sync/pull_rebase_conflict.go +++ b/pkg/integration/tests/sync/pull_rebase_conflict.go @@ -61,7 +61,7 @@ var PullRebaseConflict = NewIntegrationTest(NewIntegrationTestArgs{ SelectNextItem(). PressPrimaryAction() // choose 'content4' - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Status().Content(Equals("↑1 repo → master")) diff --git a/pkg/integration/tests/sync/pull_rebase_interactive_conflict.go b/pkg/integration/tests/sync/pull_rebase_interactive_conflict.go index bf0fc050b92..eb767a1a340 100644 --- a/pkg/integration/tests/sync/pull_rebase_interactive_conflict.go +++ b/pkg/integration/tests/sync/pull_rebase_interactive_conflict.go @@ -74,7 +74,7 @@ var PullRebaseInteractiveConflict = NewIntegrationTest(NewIntegrationTestArgs{ SelectNextItem(). PressPrimaryAction() // choose 'content4' - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Status().Content(Equals("↑2 repo → master")) diff --git a/pkg/integration/tests/sync/pull_rebase_interactive_conflict_drop.go b/pkg/integration/tests/sync/pull_rebase_interactive_conflict_drop.go index 3eee12efda0..4aff8b4e0df 100644 --- a/pkg/integration/tests/sync/pull_rebase_interactive_conflict_drop.go +++ b/pkg/integration/tests/sync/pull_rebase_interactive_conflict_drop.go @@ -83,7 +83,7 @@ var PullRebaseInteractiveConflictDrop = NewIntegrationTest(NewIntegrationTestArg SelectNextItem(). PressPrimaryAction() // choose 'content4' - t.Common().ContinueOnConflictsResolved() + t.Common().ContinueOnConflictsResolved("rebase") t.Views().Status().Content(Equals("↑1 repo → master")) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index c79dcd2f8ee..b13e42d8c90 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -128,6 +128,7 @@ var tests = []*components.IntegrationTest{ commit.ResetAuthorRange, commit.Revert, commit.RevertMerge, + commit.RevertWithConflictSingleCommit, commit.Reword, commit.Search, commit.SetAuthor, @@ -259,6 +260,7 @@ var tests = []*components.IntegrationTest{ interactive_rebase.QuickStartKeepSelection, interactive_rebase.QuickStartKeepSelectionRange, interactive_rebase.Rebase, + interactive_rebase.RebaseWithCommitThatBecomesEmpty, interactive_rebase.RewordCommitWithEditorAndFail, interactive_rebase.RewordFirstCommit, interactive_rebase.RewordLastCommit,