diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2023-07-09 21:09:52 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2023-07-10 17:12:21 +1000 |
commit | 6b9390409eb533fe87648be55e9db7d36b1d9ee3 (patch) | |
tree | 43e35b86a17dbee8aac245cc93c2645727b61148 | |
parent | 8964cedf27cbdb81f59e2400cfc89684d7458605 (diff) |
Use an interface for tasks instead of a concrete struct
By using an interface for tasks we can use a fake implementation in tests with extra methods
45 files changed, 333 insertions, 222 deletions
@@ -18,7 +18,7 @@ require ( github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d - github.com/jesseduffield/gocui v0.3.1-0.20230709105400-44d9f78b4b52 + github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e @@ -72,8 +72,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= -github.com/jesseduffield/gocui v0.3.1-0.20230709105400-44d9f78b4b52 h1:rrKgkOAVJD5rgC6aoX3zWTSiSiHkuQBA2JW/r+v1eKE= -github.com/jesseduffield/gocui v0.3.1-0.20230709105400-44d9f78b4b52/go.mod h1:dJ/BEUt3OWtaRg/PmuJWendRqREhre9JQ1SLvqrVJ8s= +github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b h1:8FmmdaYHes1m3oNyNdS+VIgkgkFpNZAWuwTnvp0tG14= +github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b/go.mod h1:dJ/BEUt3OWtaRg/PmuJWendRqREhre9JQ1SLvqrVJ8s= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= diff --git a/pkg/commands/git_commands/remote.go b/pkg/commands/git_commands/remote.go index 4366ba539..b9f20fb3a 100644 --- a/pkg/commands/git_commands/remote.go +++ b/pkg/commands/git_commands/remote.go @@ -48,7 +48,7 @@ func (self *RemoteCommands) UpdateRemoteUrl(remoteName string, updatedUrl string return self.cmd.New(cmdArgs).Run() } -func (self *RemoteCommands) DeleteRemoteBranch(task *gocui.Task, remoteName string, branchName string) error { +func (self *RemoteCommands) DeleteRemoteBranch(task gocui.Task, remoteName string, branchName string) error { cmdArgs := NewGitCmd("push"). Arg(remoteName, "--delete", branchName). ToArgv() diff --git a/pkg/commands/git_commands/sync.go b/pkg/commands/git_commands/sync.go index 901133c4d..d67c6aa79 100644 --- a/pkg/commands/git_commands/sync.go +++ b/pkg/commands/git_commands/sync.go @@ -24,7 +24,7 @@ type PushOpts struct { SetUpstream bool } -func (self *SyncCommands) PushCmdObj(task *gocui.Task, opts PushOpts) (oscommands.ICmdObj, error) { +func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (oscommands.ICmdObj, error) { if opts.UpstreamBranch != "" && opts.UpstreamRemote == "" { return nil, errors.New(self.Tr.MustSpecifyOriginError) } @@ -40,7 +40,7 @@ func (self *SyncCommands) PushCmdObj(task *gocui.Task, opts PushOpts) (oscommand return cmdObj, nil } -func (self *SyncCommands) Push(task *gocui.Task, opts PushOpts) error { +func (self *SyncCommands) Push(task gocui.Task, opts PushOpts) error { cmdObj, err := self.PushCmdObj(task, opts) if err != nil { return err @@ -49,24 +49,33 @@ func (self *SyncCommands) Push(task *gocui.Task, opts PushOpts) error { return cmdObj.Run() } -func (self *SyncCommands) Fetch(task *gocui.Task) error { +func (self *SyncCommands) FetchCmdObj(task gocui.Task) oscommands.ICmdObj { cmdArgs := NewGitCmd("fetch"). ArgIf(self.UserConfig.Git.FetchAll, "--all"). ToArgv() cmdObj := self.cmd.New(cmdArgs) cmdObj.PromptOnCredentialRequest(task) - return cmdObj.WithMutex(self.syncMutex).Run() + return cmdObj } -func (self *SyncCommands) FetchBackground() error { +func (self *SyncCommands) Fetch(task gocui.Task) error { + return self.FetchCmdObj(task).Run() +} + +func (self *SyncCommands) FetchBackgroundCmdObj() oscommands.ICmdObj { cmdArgs := NewGitCmd("fetch"). ArgIf(self.UserConfig.Git.FetchAll, "--all"). ToArgv() cmdObj := self.cmd.New(cmdArgs) cmdObj.DontLog().FailOnCredentialRequest() - return cmdObj.WithMutex(self.syncMutex).Run() + cmdObj.WithMutex(self.syncMutex) + return cmdObj +} + +func (self *SyncCommands) FetchBackground() error { + return self.FetchBackgroundCmdObj().Run() } type PullOptions struct { @@ -75,7 +84,7 @@ type PullOptions struct { FastForwardOnly bool } -func (self *SyncCommands) Pull(task *gocui.Task, opts PullOptions) error { +func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error { cmdArgs := NewGitCmd("pull"). Arg("--no-edit"). ArgIf(opts.FastForwardOnly, "--ff-only"). @@ -88,7 +97,7 @@ func (self *SyncCommands) Pull(task *gocui.Task, opts PullOptions) error { return self.cmd.New(cmdArgs).AddEnvVars("GIT_SEQUENCE_EDITOR=:").PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run() } -func (self *SyncCommands) FastForward(task *gocui.Task, branchName string, remoteName string, remoteBranchName string) error { +func (self *SyncCommands) FastForward(task gocui.Task, branchName string, remoteName string, remoteBranchName string) error { cmdArgs := NewGitCmd("fetch"). Arg(remoteName). Arg(remoteBranchName + ":" + branchName). @@ -97,7 +106,7 @@ func (self *SyncCommands) FastForward(task *gocui.Task, branchName string, remot return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run() } -func (self *SyncCommands) FetchRemote(task *gocui.Task, remoteName string) error { +func (self *SyncCommands) FetchRemote(task gocui.Task, remoteName string) error { cmdArgs := NewGitCmd("fetch"). Arg(remoteName). ToArgv() diff --git a/pkg/commands/git_commands/sync_test.go b/pkg/commands/git_commands/sync_test.go index f5eb0d403..93e6de1b1 100644 --- a/pkg/commands/git_commands/sync_test.go +++ b/pkg/commands/git_commands/sync_test.go @@ -3,6 +3,7 @@ package git_commands import ( "testing" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/stretchr/testify/assert" ) @@ -88,7 +89,8 @@ func TestSyncPush(t *testing.T) { s := s t.Run(s.testName, func(t *testing.T) { instance := buildSyncCommands(commonDeps{}) - s.test(instance.PushCmdObj(s.opts)) + task := gocui.NewFakeTask() + s.test(instance.PushCmdObj(task, s.opts)) }) } } @@ -96,7 +98,6 @@ func TestSyncPush(t *testing.T) { func TestSyncFetch(t *testing.T) { type scenario struct { testName string - opts FetchOptions fetchAllConfig bool test func(oscommands.ICmdObj) } @@ -104,7 +105,6 @@ func TestSyncFetch(t *testing.T) { scenarios := []scenario{ { testName: "Fetch in foreground (all=false)", - opts: FetchOptions{Background: false}, fetchAllConfig: false, test: func(cmdObj oscommands.ICmdObj) { assert.True(t, cmdObj.ShouldLog()) @@ -114,7 +114,6 @@ func TestSyncFetch(t *testing.T) { }, { testName: "Fetch in foreground (all=true)", - opts: FetchOptions{Background: false}, fetchAllConfig: true, test: func(cmdObj oscommands.ICmdObj) { assert.True(t, cmdObj.ShouldLog()) @@ -122,9 +121,29 @@ func TestSyncFetch(t *testing.T) { assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"}) }, }, + } + + for _, s := range scenarios { + s := s + t.Run(s.testName, func(t *testing.T) { + instance := buildSyncCommands(commonDeps{}) + instance.UserConfig.Git.FetchAll = s.fetchAllConfig + task := gocui.NewFakeTask() + s.test(instance.FetchCmdObj(task)) + }) + } +} + +func TestSyncFetchBackground(t *testing.T) { + type scenario struct { + testName string + fetchAllConfig bool + test func(oscommands.ICmdObj) + } + + scenarios := []scenario{ { testName: "Fetch in background (all=false)", - opts: FetchOptions{Background: true}, fetchAllConfig: false, test: func(cmdObj oscommands.ICmdObj) { assert.False(t, cmdObj.ShouldLog()) @@ -134,7 +153,6 @@ func TestSyncFetch(t *testing.T) { }, { testName: "Fetch in background (all=true)", - opts: FetchOptions{Background: true}, fetchAllConfig: true, test: func(cmdObj oscommands.ICmdObj) { assert.False(t, cmdObj.ShouldLog()) @@ -149,7 +167,7 @@ func TestSyncFetch(t *testing.T) { t.Run(s.testName, func(t *testing.T) { instance := buildSyncCommands(commonDeps{}) instance.UserConfig.Git.FetchAll = s.fetchAllConfig - s.test(instance.FetchCmdObj(s.opts)) + s.test(instance.FetchBackgroundCmdObj()) }) } } diff --git a/pkg/commands/git_commands/tag.go b/pkg/commands/git_commands/tag.go index e58e81d07..fb87db3b9 100644 --- a/pkg/commands/git_commands/tag.go +++ b/pkg/commands/git_commands/tag.go @@ -36,7 +36,7 @@ func (self *TagCommands) Delete(tagName string) error { return self.cmd.New(cmdArgs).Run() } -func (self *TagCommands) Push(task *gocui.Task, remoteName string, tagName string) error { +func (self *TagCommands) Push(task gocui.Task, remoteName string, tagName string) error { cmdArgs := NewGitCmd("push").Arg(remoteName, "tag", tagName). ToArgv() diff --git a/pkg/commands/oscommands/cmd_obj.go b/pkg/commands/oscommands/cmd_obj.go index a46fe9699..d8f287727 100644 --- a/pkg/commands/oscommands/cmd_obj.go +++ b/pkg/commands/oscommands/cmd_obj.go @@ -57,14 +57,14 @@ type ICmdObj interface { // returns true if IgnoreEmptyError() was called ShouldIgnoreEmptyError() bool - PromptOnCredentialRequest(task *gocui.Task) ICmdObj + PromptOnCredentialRequest(task gocui.Task) ICmdObj FailOnCredentialRequest() ICmdObj WithMutex(mutex *deadlock.Mutex) ICmdObj Mutex() *deadlock.Mutex GetCredentialStrategy() CredentialStrategy - GetTask() *gocui.Task + GetTask() gocui.Task } type CmdObj struct { @@ -87,7 +87,7 @@ type CmdObj struct { // if set to true, it means we might be asked to enter a username/password by this command. credentialStrategy CredentialStrategy - task *gocui.Task + task gocui.Task // can be set so that we don't run certain commands simultaneously mutex *deadlock.Mutex @@ -195,7 +195,7 @@ func (self *CmdObj) RunAndProcessLines(onLine func(line string) (bool, error)) e return self.runner.RunAndProcessLines(self, onLine) } -func (self *CmdObj) PromptOnCredentialRequest(task *gocui.Task) ICmdObj { +func (self *CmdObj) PromptOnCredentialRequest(task gocui.Task) ICmdObj { self.credentialStrategy = PROMPT self.task = task @@ -212,6 +212,6 @@ func (self *CmdObj) GetCredentialStrategy() CredentialStrategy { return self.credentialStrategy } -func (self *CmdObj) GetTask() *gocui.Task { +func (self *CmdObj) GetTask() gocui.Task { return self.task } diff --git a/pkg/commands/oscommands/cmd_obj_runner.go b/pkg/commands/oscommands/cmd_obj_runner.go index fc1c55f05..6dcb16b89 100644 --- a/pkg/commands/oscommands/cmd_obj_runner.go +++ b/pkg/commands/oscommands/cmd_obj_runner.go @@ -318,7 +318,7 @@ func (self *cmdObjRunner) processOutput( reader io.Reader, writer io.Writer, promptUserForCredential func(CredentialType) <-chan string, - task *gocui.Task, + task gocui.Task, ) { checkForCredentialRequest := self.getCheckForCredentialRequestFunc() diff --git a/pkg/commands/oscommands/cmd_obj_runner_test.go b/pkg/commands/oscommands/cmd_obj_runner_test.go index 3b2340649..31966cec1 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_test.go +++ b/pkg/commands/oscommands/cmd_obj_runner_test.go @@ -4,6 +4,7 @@ import ( "strings" "testing" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -111,7 +112,8 @@ func TestProcessOutput(t *testing.T) { reader := strings.NewReader(scenario.output) writer := &strings.Builder{} - runner.processOutput(reader, writer, toChanFn(scenario.promptUserForCredential)) + task := gocui.NewFakeTask() + runner.processOutput(reader, writer, toChanFn(scenario.promptUserForCredential), task) if writer.String() != scenario.expectedToWrite { t.Errorf("expected to write '%s' but got '%s'", scenario.expectedToWrite, writer.String()) diff --git a/pkg/gui/background.go b/pkg/gui/background.go index 3417d67bf..d8976549f 100644 --- a/pkg/gui/background.go +++ b/pkg/gui/background.go @@ -86,7 +86,7 @@ func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan stru if self.pauseBackgroundRefreshes { continue } - self.gui.c.OnWorker(func(*gocui.Task) { _ = function() }) + self.gui.c.OnWorker(func(gocui.Task) { _ = function() }) case <-stop: return } diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index d0ef6ee69..c55a39041 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -364,7 +364,7 @@ func (self *BranchesController) fastForward(branch *models.Branch) error { }, ) - return self.c.WithLoaderPanel(message, func(task *gocui.Task) error { + return self.c.WithLoaderPanel(message, func(task gocui.Task) error { if branch == self.c.Helpers().Refs.GetCheckedOutRef() { self.c.LogAction(action) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index f7208012e..a1cd6a9ca 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -177,7 +177,7 @@ func (self *CommitFilesController) discard(node *filetree.CommitFileNode) error Title: self.c.Tr.DiscardFileChangesTitle, Prompt: prompt, HandleConfirm: func() error { - return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { self.c.LogAction(self.c.Tr.Actions.DiscardOldFileChange) if err := self.c.Git().Rebase.DiscardOldFileChanges(self.c.Model().Commits, self.c.Contexts().LocalCommits.GetSelectedLineIdx(), node.GetPath()); err != nil { if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil { @@ -205,7 +205,7 @@ func (self *CommitFilesController) edit(node *filetree.CommitFileNode) error { func (self *CommitFilesController) toggleForPatch(node *filetree.CommitFileNode) error { toggle := func() error { - return self.c.WithWaitingStatus(self.c.Tr.UpdatingPatch, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.UpdatingPatch, func(gocui.Task) error { if !self.c.Git().Patch.PatchBuilder.Active() { if err := self.startPatchBuilder(); err != nil { return err diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index b4a35b43a..55793f8f5 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -117,7 +117,7 @@ func (self *CustomPatchOptionsMenuAction) handleDeletePatchFromCommit() error { return err } - return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { commitIndex := self.getPatchCommitIndex() self.c.LogAction(self.c.Tr.Actions.RemovePatchFromCommit) err := self.c.Git().Patch.DeletePatchesFromCommit(self.c.Model().Commits, commitIndex) @@ -134,7 +134,7 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchToSelectedCommit() erro return err } - return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { commitIndex := self.getPatchCommitIndex() self.c.LogAction(self.c.Tr.Actions.MovePatchToSelectedCommit) err := self.c.Git().Patch.MovePatchToSelectedCommit(self.c.Model().Commits, commitIndex, self.c.Contexts().LocalCommits.GetSelectedLineIdx()) @@ -152,7 +152,7 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error } pull := func(stash bool) error { - return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { commitIndex := self.getPatchCommitIndex() self.c.LogAction(self.c.Tr.Actions.MovePatchIntoIndex) err := self.c.Git().Patch.MovePatchIntoIndex(self.c.Model().Commits, commitIndex, stash) @@ -182,7 +182,7 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error { return err } - return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error { commitIndex := self.getPatchCommitIndex() self.c.LogAction(self.c.Tr.Actions.MovePatchIntoNewCommit) err := self.c.Git().Patch.PullPatchIntoNewCommit(self.c.Model().Commits, commitIndex) diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 8f43162cf..6d4647e01 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -800,7 +800,7 @@ func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) e } func (self *FilesController) fetch() error { - return self.c.WithLoaderPanel(self.c.Tr.FetchWait, func(task *gocui.Task) error { + return self.c.WithLoaderPanel(self.c.Tr.FetchWait, func(task gocui.Task) error { if err := self.fetchAux(task); err != nil { _ = self.c.Error(err) } @@ -808,7 +808,7 @@ func (self *FilesController) fetch() error { }) } -func (self *FilesController) fetchAux(task *gocui.Task) (err error) { +func (self *FilesController) fetchAux(task gocui.Task) (err error) { self.c.LogAction("Fetch") err = self.c.Git().Sync.Fetch(task) diff --git a/pkg/gui/controllers/files_remove_controller.go b/pkg/gui/controllers/files_remove_controller.go index 8e1751c64..dd3a3c9c5 100644 --- a/pkg/gui/controllers/files_remove_controller.go +++ b/pkg/gui/controllers/files_remove_controller.go @@ -146,7 +146,7 @@ func (self *FilesRemoveController) remove(node *filetree.FileNode) error { } func (self *FilesRemoveController) ResetSubmodule(submodule *models.SubmoduleConfig) error { - return self.c.WithWaitingStatus(self.c.Tr.ResettingSubmoduleStatus, func(*gocui.Task) error { + return self.c.WithWaitingStatus(self.c.Tr.ResettingSubmoduleStatus, func(gocui.Task) error { self.c.LogAction(self.c.Tr.Actions.ResetSubmodule) file := self.c.Helpers().WorkingTree.FileForSubmodule(submodule) diff --git a/pkg/gui/controllers/helpers/app_status_helper.go b/pkg/gui/controllers/helpers/app_status_helper.go index e271e1999..e3b6931ad 100644 --- a/pkg/gui/controllers/helpers/app_status_helper.go +++ b/pkg/gui/controllers/helpers/app_status_helper.go @@ -27,8 +27,8 @@ func (self *AppStatusHelper) Toast(message string) { } // withWaitingStatus wraps a function and shows a waiting status while the function is still executing -func (self *AppStatusHelper) WithWaitingStatus(message string, f func(*gocui.Task) error) { - self.c.OnWorker(func(task *gocui.Task) { +func (self *AppStatusHelper) WithWaitingStatus(message string, f func(gocui.Task) error) { + self.c.OnWorker(func(task gocui.Task) { self.statusMgr().WithWaitingStatus(message, func() { self.renderAppStatus() @@ -50,7 +50,7 @@ func (self *AppStatusHelper) GetStatusString() string { } func (self *AppStatusHelper) renderAppStatus() { - self.c.OnWorker(func(_ *gocui.Task) { + self.c.OnWorker(func(_ gocui.Task) { ticker := time.NewTicker(time.Millisecond * 50) defer ticker.Stop() for range ticker.C { diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go index 9797b3ef3..2e8a11f7d 100644 --- a/pkg/gui/controllers/helpers/cherry_pick_helper.go +++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go @@ -76,7 +76,7 @@ func (self *CherryPickHelper) Paste() error { Title: self.c.Tr.CherryPick, Prompt: self.c.Tr.SureCherryPick, HandleConfirm: func() error { - return self.c.WithWaitingStatus(self |