diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index fdaf8d9ff..22050b384 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -171,7 +171,7 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod } } - if !self.getWorkingTreeState().IsRebasing() { + if !self.getWorkingTreeState().Rebasing { // not in rebase mode so return original commits return result, nil } diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go index 0641f2476..f7b075134 100644 --- a/pkg/commands/git_commands/commit_loader_test.go +++ b/pkg/commands/git_commands/commit_loader_test.go @@ -303,7 +303,7 @@ func TestGetCommits(t *testing.T) { builder := &CommitLoader{ Common: common, cmd: cmd, - getWorkingTreeState: func() models.WorkingTreeState { return models.WORKING_TREE_STATE_NONE }, + getWorkingTreeState: func() models.WorkingTreeState { return models.WorkingTreeState{} }, dotGitDir: ".git", readFile: func(filename string) ([]byte, error) { return []byte(""), nil @@ -486,7 +486,7 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) { builder := &CommitLoader{ Common: common, cmd: oscommands.NewDummyCmdObjBuilder(oscommands.NewFakeRunner(t)), - getWorkingTreeState: func() models.WorkingTreeState { return models.WORKING_TREE_STATE_REBASING }, + 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 a76121186..77563ab88 100644 --- a/pkg/commands/git_commands/patch.go +++ b/pkg/commands/git_commands/patch.go @@ -228,7 +228,7 @@ func (self *PatchCommands) MovePatchIntoIndex(commits []*models.Commit, commitId } if err := self.ApplyCustomPatch(true, true); err != nil { - if self.status.WorkingTreeState() == models.WORKING_TREE_STATE_REBASING { + if self.status.WorkingTreeState().Rebasing { _ = self.rebase.AbortRebase() } return err @@ -252,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() == models.WORKING_TREE_STATE_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 a0d68e241..ff09e22bc 100644 --- a/pkg/commands/git_commands/status.go +++ b/pkg/commands/git_commands/status.go @@ -21,15 +21,12 @@ func NewStatusCommands( } func (self *StatusCommands) WorkingTreeState() models.WorkingTreeState { - isInRebase, _ := self.IsInRebase() - if isInRebase { - return models.WORKING_TREE_STATE_REBASING - } - merging, _ := self.IsInMergeState() - if merging { - return models.WORKING_TREE_STATE_MERGING - } - return models.WORKING_TREE_STATE_NONE + 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 { @@ -49,6 +46,42 @@ 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 index bb8f6536b..3e7bdbf1b 100644 --- a/pkg/commands/models/working_tree_state.go +++ b/pkg/commands/models/working_tree_state.go @@ -2,62 +2,111 @@ package models import "github.com/jesseduffield/lazygit/pkg/i18n" -type WorkingTreeState int - -const ( - // this means we're neither rebasing nor merging - WORKING_TREE_STATE_NONE WorkingTreeState = iota - WORKING_TREE_STATE_REBASING - WORKING_TREE_STATE_MERGING -) - -func (self WorkingTreeState) IsMerging() bool { - return self == WORKING_TREE_STATE_MERGING +// 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) IsRebasing() bool { - return self == WORKING_TREE_STATE_REBASING +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 { - switch self { - case WORKING_TREE_STATE_REBASING: - return tr.RebasingStatus - case WORKING_TREE_STATE_MERGING: - return tr.MergingStatus - default: - // should never actually display this - return "none" - } + 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 { - switch self { - case WORKING_TREE_STATE_REBASING: - return tr.LowercaseRebasingStatus - case WORKING_TREE_STATE_MERGING: - return tr.LowercaseMergingStatus - default: - // should never actually display this - return "none" - } + 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 { - if self == WORKING_TREE_STATE_MERGING { - return tr.MergeOptionsTitle - } - return tr.RebaseOptionsTitle + 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 { - switch self { - case WORKING_TREE_STATE_MERGING: - return "merge" - case WORKING_TREE_STATE_REBASING: - return "rebase" - default: - // shouldn't be possible to land here - return "" - } + 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/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index a286241da..f40f7f0ff 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -40,7 +40,7 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext { } } - showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == models.WORKING_TREE_STATE_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 ca06d5fd2..f231152db 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/models" "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() == models.WORKING_TREE_STATE_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() != models.WORKING_TREE_STATE_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/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index dbb10fac6..f8c328958 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -50,7 +50,7 @@ func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error { {option: REBASE_OPTION_ABORT, key: 'a'}, } - if self.c.Git().Status.WorkingTreeState() == models.WORKING_TREE_STATE_REBASING { + if self.c.Git().Status.WorkingTreeState().CanSkip() { options = append(options, optionAndKey{ option: REBASE_OPTION_SKIP, key: 's', }) @@ -77,12 +77,13 @@ func (self *MergeAndRebaseHelper) ContinueRebase() error { func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { status := self.c.Git().Status.WorkingTreeState() - if status != models.WORKING_TREE_STATE_MERGING && status != models.WORKING_TREE_STATE_REBASING { + if status.None() { return errors.New(self.c.Tr.NotMergingOrRebasing) } self.c.LogAction(fmt.Sprintf("Merge/Rebase: %s", command)) - if status == models.WORKING_TREE_STATE_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"), ) @@ -101,10 +102,10 @@ 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 - needsSubprocess := (status == models.WORKING_TREE_STATE_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 == models.WORKING_TREE_STATE_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 diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go index b5b3df7ac..8c6b46eb6 100644 --- a/pkg/gui/controllers/helpers/mode_helper.go +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/samber/lo" @@ -115,7 +114,7 @@ func (self *ModeHelper) Statuses() []ModeStatus { }, { IsActive: func() bool { - return !self.suppressRebasingMode && self.c.Git().Status.WorkingTreeState() != models.WORKING_TREE_STATE_NONE + return !self.suppressRebasingMode && self.c.Git().Status.WorkingTreeState().Any() }, Description: func() string { workingTreeState := self.c.Git().Status.WorkingTreeState() diff --git a/pkg/gui/controllers/helpers/patch_building_helper.go b/pkg/gui/controllers/helpers/patch_building_helper.go index 700cfff6a..73d0fb608 100644 --- a/pkg/gui/controllers/helpers/patch_building_helper.go +++ b/pkg/gui/controllers/helpers/patch_building_helper.go @@ -3,7 +3,6 @@ package helpers import ( "errors" - "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/patch" "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() != models.WORKING_TREE_STATE_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 a05860324..93ad110f3 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -582,7 +582,7 @@ func (self *RefreshHelper) refreshStateFiles() error { } } - if self.c.Git().Status.WorkingTreeState() != models.WORKING_TREE_STATE_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 7487d3def..260f42cf7 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -681,7 +681,7 @@ func (self *LocalCommitsController) rewordEnabled(commit *models.Commit) *types. } func (self *LocalCommitsController) isRebasing() bool { - return self.c.Model().WorkingTreeStateAtLastCommitRefresh != models.WORKING_TREE_STATE_NONE + return self.c.Model().WorkingTreeStateAtLastCommitRefresh.Any() } func (self *LocalCommitsController) moveDown(selectedCommits []*models.Commit, startIdx int, endIdx int) error { @@ -975,7 +975,7 @@ func (self *LocalCommitsController) moveFixupCommitToOwnerStackedBranch(targetCo return nil } - if self.c.Git().Status.WorkingTreeState() != models.WORKING_TREE_STATE_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 73d36c0f7..8d173f46c 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/models" "github.com/jesseduffield/lazygit/pkg/constants" "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/style" @@ -109,8 +108,7 @@ 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 models.WORKING_TREE_STATE_REBASING, models.WORKING_TREE_STATE_MERGING: + if workingTreeState.Any() { workingTreeStatus := fmt.Sprintf("(%s)", workingTreeState.LowerCaseTitle(self.c.Tr)) if cursorInSubstring(opts.X, upstreamStatus+" ", workingTreeStatus) { return self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu() @@ -118,10 +116,8 @@ func (self *StatusController) onClick(opts gocui.ViewMouseBindingOpts) error { 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 1150975bc..9922f73d6 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/models" "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() == models.WORKING_TREE_STATE_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() == models.WORKING_TREE_STATE_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 4f9836551..347db7589 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 e09aab5f3..b636df647 100644 --- a/pkg/gui/presentation/status.go +++ b/pkg/gui/presentation/status.go @@ -30,7 +30,7 @@ func FormatStatus( } } - if workingTreeState != models.WORKING_TREE_STATE_NONE { + if workingTreeState.Any() { status += style.FgYellow.Sprintf("(%s) ", workingTreeState.LowerCaseTitle(tr)) } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index b2deb7ab1..f3713e048 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", @@ -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",