Remove ICmdObj interface

It is only implemented by *CmdObj, so use that directly in client code.
This commit is contained in:
Stefan Haller 2025-04-29 19:10:36 +02:00
parent 4e3d09e9d8
commit a400ef0079
25 changed files with 137 additions and 178 deletions

View file

@ -30,11 +30,11 @@ func NewGitCmdObjBuilder(log *logrus.Entry, innerBuilder *oscommands.CmdObjBuild
var defaultEnvVar = "GIT_OPTIONAL_LOCKS=0" var defaultEnvVar = "GIT_OPTIONAL_LOCKS=0"
func (self *gitCmdObjBuilder) New(args []string) oscommands.ICmdObj { func (self *gitCmdObjBuilder) New(args []string) *oscommands.CmdObj {
return self.innerBuilder.New(args).AddEnvVars(defaultEnvVar) return self.innerBuilder.New(args).AddEnvVars(defaultEnvVar)
} }
func (self *gitCmdObjBuilder) NewShell(cmdStr string, shellFunctionsFile string) oscommands.ICmdObj { func (self *gitCmdObjBuilder) NewShell(cmdStr string, shellFunctionsFile string) *oscommands.CmdObj {
return self.innerBuilder.NewShell(cmdStr, shellFunctionsFile).AddEnvVars(defaultEnvVar) return self.innerBuilder.NewShell(cmdStr, shellFunctionsFile).AddEnvVars(defaultEnvVar)
} }

View file

@ -20,12 +20,12 @@ type gitCmdObjRunner struct {
innerRunner oscommands.ICmdObjRunner innerRunner oscommands.ICmdObjRunner
} }
func (self *gitCmdObjRunner) Run(cmdObj oscommands.ICmdObj) error { func (self *gitCmdObjRunner) Run(cmdObj *oscommands.CmdObj) error {
_, err := self.RunWithOutput(cmdObj) _, err := self.RunWithOutput(cmdObj)
return err return err
} }
func (self *gitCmdObjRunner) RunWithOutput(cmdObj oscommands.ICmdObj) (string, error) { func (self *gitCmdObjRunner) RunWithOutput(cmdObj *oscommands.CmdObj) (string, error) {
var output string var output string
var err error var err error
for i := 0; i < RetryCount; i++ { for i := 0; i < RetryCount; i++ {
@ -44,7 +44,7 @@ func (self *gitCmdObjRunner) RunWithOutput(cmdObj oscommands.ICmdObj) (string, e
return output, err return output, err
} }
func (self *gitCmdObjRunner) RunWithOutputs(cmdObj oscommands.ICmdObj) (string, string, error) { func (self *gitCmdObjRunner) RunWithOutputs(cmdObj *oscommands.CmdObj) (string, string, error) {
var stdout, stderr string var stdout, stderr string
var err error var err error
for i := 0; i < RetryCount; i++ { for i := 0; i < RetryCount; i++ {
@ -64,6 +64,6 @@ func (self *gitCmdObjRunner) RunWithOutputs(cmdObj oscommands.ICmdObj) (string,
} }
// Retry logic not implemented here, but these commands typically don't need to obtain a lock. // Retry logic not implemented here, but these commands typically don't need to obtain a lock.
func (self *gitCmdObjRunner) RunAndProcessLines(cmdObj oscommands.ICmdObj, onLine func(line string) (bool, error)) error { func (self *gitCmdObjRunner) RunAndProcessLines(cmdObj *oscommands.CmdObj, onLine func(line string) (bool, error)) error {
return self.innerRunner.RunAndProcessLines(cmdObj, onLine) return self.innerRunner.RunAndProcessLines(cmdObj, onLine)
} }

View file

@ -154,7 +154,7 @@ func (self *BranchCommands) GetGraph(branchName string) (string, error) {
return self.GetGraphCmdObj(branchName).DontLog().RunWithOutput() return self.GetGraphCmdObj(branchName).DontLog().RunWithOutput()
} }
func (self *BranchCommands) GetGraphCmdObj(branchName string) oscommands.ICmdObj { func (self *BranchCommands) GetGraphCmdObj(branchName string) *oscommands.CmdObj {
branchLogCmdTemplate := self.UserConfig().Git.BranchLogCmd branchLogCmdTemplate := self.UserConfig().Git.BranchLogCmd
templateValues := map[string]string{ templateValues := map[string]string{
"branchName": self.cmd.Quote(branchName), "branchName": self.cmd.Quote(branchName),
@ -255,7 +255,7 @@ func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
return self.cmd.New(cmdArgs).Run() return self.cmd.New(cmdArgs).Run()
} }
func (self *BranchCommands) AllBranchesLogCmdObj() oscommands.ICmdObj { func (self *BranchCommands) AllBranchesLogCmdObj() *oscommands.CmdObj {
// Only choose between non-empty, non-identical commands // Only choose between non-empty, non-identical commands
candidates := lo.Uniq(lo.WithoutEmpty(append([]string{ candidates := lo.Uniq(lo.WithoutEmpty(append([]string{
self.UserConfig().Git.AllBranchesLogCmd, self.UserConfig().Git.AllBranchesLogCmd,

View file

@ -85,7 +85,7 @@ func (self *CommitCommands) ResetToCommit(hash string, strength string, envVars
Run() Run()
} }
func (self *CommitCommands) CommitCmdObj(summary string, description string, forceSkipHooks bool) oscommands.ICmdObj { func (self *CommitCommands) CommitCmdObj(summary string, description string, forceSkipHooks bool) *oscommands.CmdObj {
messageArgs := self.commitMessageArgs(summary, description) messageArgs := self.commitMessageArgs(summary, description)
skipHookPrefix := self.UserConfig().Git.SkipHookPrefix skipHookPrefix := self.UserConfig().Git.SkipHookPrefix
cmdArgs := NewGitCmd("commit"). cmdArgs := NewGitCmd("commit").
@ -97,16 +97,16 @@ func (self *CommitCommands) CommitCmdObj(summary string, description string, for
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *CommitCommands) RewordLastCommitInEditorCmdObj() oscommands.ICmdObj { func (self *CommitCommands) RewordLastCommitInEditorCmdObj() *oscommands.CmdObj {
return self.cmd.New(NewGitCmd("commit").Arg("--allow-empty", "--amend", "--only").ToArgv()) return self.cmd.New(NewGitCmd("commit").Arg("--allow-empty", "--amend", "--only").ToArgv())
} }
func (self *CommitCommands) RewordLastCommitInEditorWithMessageFileCmdObj(tmpMessageFile string) oscommands.ICmdObj { func (self *CommitCommands) RewordLastCommitInEditorWithMessageFileCmdObj(tmpMessageFile string) *oscommands.CmdObj {
return self.cmd.New(NewGitCmd("commit"). return self.cmd.New(NewGitCmd("commit").
Arg("--allow-empty", "--amend", "--only", "--edit", "--file="+tmpMessageFile).ToArgv()) Arg("--allow-empty", "--amend", "--only", "--edit", "--file="+tmpMessageFile).ToArgv())
} }
func (self *CommitCommands) CommitInEditorWithMessageFileCmdObj(tmpMessageFile string, forceSkipHooks bool) oscommands.ICmdObj { func (self *CommitCommands) CommitInEditorWithMessageFileCmdObj(tmpMessageFile string, forceSkipHooks bool) *oscommands.CmdObj {
return self.cmd.New(NewGitCmd("commit"). return self.cmd.New(NewGitCmd("commit").
ArgIf(forceSkipHooks, "--no-verify"). ArgIf(forceSkipHooks, "--no-verify").
Arg("--edit"). Arg("--edit").
@ -116,7 +116,7 @@ func (self *CommitCommands) CommitInEditorWithMessageFileCmdObj(tmpMessageFile s
} }
// RewordLastCommit rewords the topmost commit with the given message // RewordLastCommit rewords the topmost commit with the given message
func (self *CommitCommands) RewordLastCommit(summary string, description string) oscommands.ICmdObj { func (self *CommitCommands) RewordLastCommit(summary string, description string) *oscommands.CmdObj {
messageArgs := self.commitMessageArgs(summary, description) messageArgs := self.commitMessageArgs(summary, description)
cmdArgs := NewGitCmd("commit"). cmdArgs := NewGitCmd("commit").
@ -138,7 +138,7 @@ func (self *CommitCommands) commitMessageArgs(summary string, description string
} }
// runs git commit without the -m argument meaning it will invoke the user's editor // runs git commit without the -m argument meaning it will invoke the user's editor
func (self *CommitCommands) CommitEditorCmdObj() oscommands.ICmdObj { func (self *CommitCommands) CommitEditorCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("commit"). cmdArgs := NewGitCmd("commit").
ArgIf(self.signoffFlag() != "", self.signoffFlag()). ArgIf(self.signoffFlag() != "", self.signoffFlag()).
ToArgv() ToArgv()
@ -246,7 +246,7 @@ func (self *CommitCommands) AmendHead() error {
return self.AmendHeadCmdObj().Run() return self.AmendHeadCmdObj().Run()
} }
func (self *CommitCommands) AmendHeadCmdObj() oscommands.ICmdObj { func (self *CommitCommands) AmendHeadCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("commit"). cmdArgs := NewGitCmd("commit").
Arg("--amend", "--no-edit", "--allow-empty"). Arg("--amend", "--no-edit", "--allow-empty").
ToArgv() ToArgv()
@ -254,7 +254,7 @@ func (self *CommitCommands) AmendHeadCmdObj() oscommands.ICmdObj {
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) oscommands.ICmdObj { func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) *oscommands.CmdObj {
contextSize := self.AppState.DiffContextSize contextSize := self.AppState.DiffContextSize
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
@ -278,7 +278,7 @@ func (self *CommitCommands) ShowCmdObj(hash string, filterPath string) oscommand
return self.cmd.New(cmdArgs).DontLog() return self.cmd.New(cmdArgs).DontLog()
} }
func (self *CommitCommands) ShowFileContentCmdObj(hash string, filePath string) oscommands.ICmdObj { func (self *CommitCommands) ShowFileContentCmdObj(hash string, filePath string) *oscommands.CmdObj {
cmdArgs := NewGitCmd("show"). cmdArgs := NewGitCmd("show").
Arg(fmt.Sprintf("%s:%s", hash, filePath)). Arg(fmt.Sprintf("%s:%s", hash, filePath)).
ToArgv() ToArgv()

View file

@ -583,7 +583,7 @@ func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
} }
// getLog gets the git log. // getLog gets the git log.
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj { func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) *oscommands.CmdObj {
gitLogOrder := self.AppState.GitLogOrder gitLogOrder := self.AppState.GitLogOrder
refSpec := opts.RefName refSpec := opts.RefName

View file

@ -18,7 +18,7 @@ func NewDiffCommands(gitCommon *GitCommon) *DiffCommands {
// This is for generating diffs to be shown in the UI (e.g. rendering a range // This is for generating diffs to be shown in the UI (e.g. rendering a range
// diff to the main view). It uses a custom pager if one is configured. // diff to the main view). It uses a custom pager if one is configured.
func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj { func (self *DiffCommands) DiffCmdObj(diffArgs []string) *oscommands.CmdObj {
extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand extDiffCmd := self.UserConfig().Git.Paging.ExternalDiffCommand
useExtDiff := extDiffCmd != "" useExtDiff := extDiffCmd != ""
ignoreWhitespace := self.AppState.IgnoreWhitespaceInDiffView ignoreWhitespace := self.AppState.IgnoreWhitespaceInDiffView
@ -83,7 +83,7 @@ type DiffToolCmdOptions struct {
Staged bool Staged bool
} }
func (self *DiffCommands) OpenDiffToolCmdObj(opts DiffToolCmdOptions) oscommands.ICmdObj { func (self *DiffCommands) OpenDiffToolCmdObj(opts DiffToolCmdOptions) *oscommands.CmdObj {
return self.cmd.New(NewGitCmd("difftool"). return self.cmd.New(NewGitCmd("difftool").
Arg("--no-prompt"). Arg("--no-prompt").
ArgIf(opts.IsDirectory, "--dir-diff"). ArgIf(opts.IsDirectory, "--dir-diff").
@ -95,7 +95,7 @@ func (self *DiffCommands) OpenDiffToolCmdObj(opts DiffToolCmdOptions) oscommands
ToArgv()) ToArgv())
} }
func (self *DiffCommands) DiffIndexCmdObj(diffArgs ...string) oscommands.ICmdObj { func (self *DiffCommands) DiffIndexCmdObj(diffArgs ...string) *oscommands.CmdObj {
return self.cmd.New( return self.cmd.New(
NewGitCmd("diff-index"). NewGitCmd("diff-index").
Config("diff.noprefix=false"). Config("diff.noprefix=false").

View file

@ -24,7 +24,7 @@ func (self *FlowCommands) GitFlowEnabled() bool {
return self.config.GetGitFlowPrefixes() != "" return self.config.GetGitFlowPrefixes() != ""
} }
func (self *FlowCommands) FinishCmdObj(branchName string) (oscommands.ICmdObj, error) { func (self *FlowCommands) FinishCmdObj(branchName string) (*oscommands.CmdObj, error) {
prefixes := self.config.GetGitFlowPrefixes() prefixes := self.config.GetGitFlowPrefixes()
// need to find out what kind of branch this is // need to find out what kind of branch this is
@ -54,7 +54,7 @@ func (self *FlowCommands) FinishCmdObj(branchName string) (oscommands.ICmdObj, e
return self.cmd.New(cmdArgs), nil return self.cmd.New(cmdArgs), nil
} }
func (self *FlowCommands) StartCmdObj(branchType string, name string) oscommands.ICmdObj { func (self *FlowCommands) StartCmdObj(branchType string, name string) *oscommands.CmdObj {
cmdArgs := NewGitCmd("flow").Arg(branchType, "start", name).ToArgv() cmdArgs := NewGitCmd("flow").Arg(branchType, "start", name).ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)

View file

@ -53,7 +53,7 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, su
return self.ContinueRebase() return self.ContinueRebase()
} }
func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (oscommands.ICmdObj, error) { func (self *RebaseCommands) RewordCommitInEditor(commits []*models.Commit, index int) (*oscommands.CmdObj, error) {
changes := []daemon.ChangeTodoAction{{ changes := []daemon.ChangeTodoAction{{
Hash: commits[index].Hash(), Hash: commits[index].Hash(),
NewAction: todo.Reword, NewAction: todo.Reword,
@ -209,7 +209,7 @@ type PrepareInteractiveRebaseCommandOpts struct {
// PrepareInteractiveRebaseCommand returns the cmd for an interactive rebase // PrepareInteractiveRebaseCommand returns the cmd for an interactive rebase
// we tell git to run lazygit to edit the todo list, and we pass the client // we tell git to run lazygit to edit the todo list, and we pass the client
// lazygit instructions what to do with the todo file // lazygit instructions what to do with the todo file
func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteractiveRebaseCommandOpts) oscommands.ICmdObj { func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteractiveRebaseCommandOpts) *oscommands.CmdObj {
ex := oscommands.GetLazygitPath() ex := oscommands.GetLazygitPath()
cmdArgs := NewGitCmd("rebase"). cmdArgs := NewGitCmd("rebase").
@ -446,7 +446,7 @@ func (self *RebaseCommands) RebaseBranchFromBaseCommit(targetBranchName string,
}).Run() }).Run()
} }
func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) oscommands.ICmdObj { func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) *oscommands.CmdObj {
cmdArgs := NewGitCmd(commandType).Arg("--" + command).ToArgv() cmdArgs := NewGitCmd(commandType).Arg("--" + command).ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
@ -485,7 +485,7 @@ func (self *RebaseCommands) GenericMergeOrRebaseAction(commandType string, comma
return nil return nil
} }
func (self *RebaseCommands) runSkipEditorCommand(cmdObj oscommands.ICmdObj) error { func (self *RebaseCommands) runSkipEditorCommand(cmdObj *oscommands.CmdObj) error {
instruction := daemon.NewExitImmediatelyInstruction() instruction := daemon.NewExitImmediatelyInstruction()
lazyGitPath := oscommands.GetLazygitPath() lazyGitPath := oscommands.GetLazygitPath()
return cmdObj. return cmdObj.

View file

@ -69,7 +69,7 @@ func TestRebaseRebaseBranch(t *testing.T) {
// environment variables that suppress an interactive editor // environment variables that suppress an interactive editor
func TestRebaseSkipEditorCommand(t *testing.T) { func TestRebaseSkipEditorCommand(t *testing.T) {
cmdArgs := []string{"git", "blah"} cmdArgs := []string{"git", "blah"}
runner := oscommands.NewFakeRunner(t).ExpectFunc("matches editor env var", func(cmdObj oscommands.ICmdObj) bool { runner := oscommands.NewFakeRunner(t).ExpectFunc("matches editor env var", func(cmdObj *oscommands.CmdObj) bool {
assert.EqualValues(t, cmdArgs, cmdObj.Args()) assert.EqualValues(t, cmdArgs, cmdObj.Args())
envVars := cmdObj.GetEnvVars() envVars := cmdObj.GetEnvVars()
for _, regexStr := range []string{ for _, regexStr := range []string{

View file

@ -80,7 +80,7 @@ func (self *StashCommands) Hash(index int) (string, error) {
return strings.Trim(hash, "\r\n"), err return strings.Trim(hash, "\r\n"), err
} }
func (self *StashCommands) ShowStashEntryCmdObj(index int) oscommands.ICmdObj { func (self *StashCommands) ShowStashEntryCmdObj(index int) *oscommands.CmdObj {
// "-u" is the same as "--include-untracked", but the latter fails in older git versions for some reason // "-u" is the same as "--include-untracked", but the latter fails in older git versions for some reason
cmdArgs := NewGitCmd("stash").Arg("show"). cmdArgs := NewGitCmd("stash").Arg("show").
Arg("-p"). Arg("-p").

View file

@ -237,35 +237,35 @@ func (self *SubmoduleCommands) Update(path string) error {
return self.cmd.New(cmdArgs).Run() return self.cmd.New(cmdArgs).Run()
} }
func (self *SubmoduleCommands) BulkInitCmdObj() oscommands.ICmdObj { func (self *SubmoduleCommands) BulkInitCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("submodule").Arg("init"). cmdArgs := NewGitCmd("submodule").Arg("init").
ToArgv() ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *SubmoduleCommands) BulkUpdateCmdObj() oscommands.ICmdObj { func (self *SubmoduleCommands) BulkUpdateCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("submodule").Arg("update"). cmdArgs := NewGitCmd("submodule").Arg("update").
ToArgv() ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *SubmoduleCommands) ForceBulkUpdateCmdObj() oscommands.ICmdObj { func (self *SubmoduleCommands) ForceBulkUpdateCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("submodule").Arg("update", "--force"). cmdArgs := NewGitCmd("submodule").Arg("update", "--force").
ToArgv() ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *SubmoduleCommands) BulkUpdateRecursivelyCmdObj() oscommands.ICmdObj { func (self *SubmoduleCommands) BulkUpdateRecursivelyCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("submodule").Arg("update", "--init", "--recursive"). cmdArgs := NewGitCmd("submodule").Arg("update", "--init", "--recursive").
ToArgv() ToArgv()
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *SubmoduleCommands) BulkDeinitCmdObj() oscommands.ICmdObj { func (self *SubmoduleCommands) BulkDeinitCmdObj() *oscommands.CmdObj {
cmdArgs := NewGitCmd("submodule").Arg("deinit", "--all", "--force"). cmdArgs := NewGitCmd("submodule").Arg("deinit", "--all", "--force").
ToArgv() ToArgv()

View file

@ -28,7 +28,7 @@ type PushOpts struct {
SetUpstream bool SetUpstream bool
} }
func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (oscommands.ICmdObj, error) { func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (*oscommands.CmdObj, error) {
if opts.UpstreamBranch != "" && opts.UpstreamRemote == "" { if opts.UpstreamBranch != "" && opts.UpstreamRemote == "" {
return nil, errors.New(self.Tr.MustSpecifyOriginError) return nil, errors.New(self.Tr.MustSpecifyOriginError)
} }
@ -62,7 +62,7 @@ func (self *SyncCommands) fetchCommandBuilder(fetchAll bool) *GitCommandBuilder
ArgIf(self.version.IsAtLeast(2, 29, 0), "--no-write-fetch-head") ArgIf(self.version.IsAtLeast(2, 29, 0), "--no-write-fetch-head")
} }
func (self *SyncCommands) FetchCmdObj(task gocui.Task) oscommands.ICmdObj { func (self *SyncCommands) FetchCmdObj(task gocui.Task) *oscommands.CmdObj {
cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv() cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv()
cmdObj := self.cmd.New(cmdArgs) cmdObj := self.cmd.New(cmdArgs)
@ -74,7 +74,7 @@ func (self *SyncCommands) Fetch(task gocui.Task) error {
return self.FetchCmdObj(task).Run() return self.FetchCmdObj(task).Run()
} }
func (self *SyncCommands) FetchBackgroundCmdObj() oscommands.ICmdObj { func (self *SyncCommands) FetchBackgroundCmdObj() *oscommands.CmdObj {
cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv() cmdArgs := self.fetchCommandBuilder(self.UserConfig().Git.FetchAll).ToArgv()
cmdObj := self.cmd.New(cmdArgs) cmdObj := self.cmd.New(cmdArgs)

View file

@ -12,14 +12,14 @@ func TestSyncPush(t *testing.T) {
type scenario struct { type scenario struct {
testName string testName string
opts PushOpts opts PushOpts
test func(oscommands.ICmdObj, error) test func(*oscommands.CmdObj, error)
} }
scenarios := []scenario{ scenarios := []scenario{
{ {
testName: "Push with force disabled", testName: "Push with force disabled",
opts: PushOpts{ForceWithLease: false}, opts: PushOpts{ForceWithLease: false},
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -27,7 +27,7 @@ func TestSyncPush(t *testing.T) {
{ {
testName: "Push with force-with-lease enabled", testName: "Push with force-with-lease enabled",
opts: PushOpts{ForceWithLease: true}, opts: PushOpts{ForceWithLease: true},
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -35,7 +35,7 @@ func TestSyncPush(t *testing.T) {
{ {
testName: "Push with force enabled", testName: "Push with force enabled",
opts: PushOpts{Force: true}, opts: PushOpts{Force: true},
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -48,7 +48,7 @@ func TestSyncPush(t *testing.T) {
UpstreamRemote: "origin", UpstreamRemote: "origin",
UpstreamBranch: "master", UpstreamBranch: "master",
}, },
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push", "origin", "refs/heads/master:master"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push", "origin", "refs/heads/master:master"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -62,7 +62,7 @@ func TestSyncPush(t *testing.T) {
UpstreamBranch: "master", UpstreamBranch: "master",
SetUpstream: true, SetUpstream: true,
}, },
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--set-upstream", "origin", "refs/heads/master-local:master"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--set-upstream", "origin", "refs/heads/master-local:master"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -76,7 +76,7 @@ func TestSyncPush(t *testing.T) {
UpstreamBranch: "master", UpstreamBranch: "master",
SetUpstream: true, SetUpstream: true,
}, },
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease", "--set-upstream", "origin", "refs/heads/master:master"}) assert.Equal(t, cmdObj.Args(), []string{"git", "push", "--force-with-lease", "--set-upstream", "origin", "refs/heads/master:master"})
assert.NoError(t, err) assert.NoError(t, err)
}, },
@ -89,7 +89,7 @@ func TestSyncPush(t *testing.T) {
UpstreamBranch: "master", UpstreamBranch: "master",
SetUpstream: true, SetUpstream: true,
}, },
test: func(cmdObj oscommands.ICmdObj, err error) { test: func(cmdObj *oscommands.CmdObj, err error) {
assert.Error(t, err) assert.Error(t, err)
assert.EqualValues(t, "Must specify a remote if specifying a branch", err.Error()) assert.EqualValues(t, "Must specify a remote if specifying a branch", err.Error())
}, },
@ -109,14 +109,14 @@ func TestSyncFetch(t *testing.T) {
type scenario struct { type scenario struct {
testName string testName string
fetchAllConfig bool fetchAllConfig bool
test func(oscommands.ICmdObj) test func(*oscommands.CmdObj)
} }
scenarios := []scenario{ scenarios := []scenario{
{ {
testName: "Fetch in foreground (all=false)", testName: "Fetch in foreground (all=false)",
fetchAllConfig: false, fetchAllConfig: false,
test: func(cmdObj oscommands.ICmdObj) { test: func(cmdObj *oscommands.CmdObj) {
assert.True(t, cmdObj.ShouldLog()) assert.True(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT) assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"}) assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"})
@ -125,7 +125,7 @@ func TestSyncFetch(t *testing.T) {
{ {
testName: "Fetch in foreground (all=true)", testName: "Fetch in foreground (all=true)",
fetchAllConfig: true, fetchAllConfig: true,
test: func(cmdObj oscommands.ICmdObj) { test: func(cmdObj *oscommands.CmdObj) {
assert.True(t, cmdObj.ShouldLog()) assert.True(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT) assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.PROMPT)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"}) assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"})
@ -147,14 +147,14 @@ func TestSyncFetchBackground(t *testing.T) {
type scenario struct { type scenario struct {
testName string testName string
fetchAllConfig bool fetchAllConfig bool
test func(oscommands.ICmdObj) test func(*oscommands.CmdObj)
} }
scenarios := []scenario{ scenarios := []scenario{
{ {
testName: "Fetch in background (all=false)", testName: "Fetch in background (all=false)",
fetchAllConfig: false, fetchAllConfig: false,
test: func(cmdObj oscommands.ICmdObj) { test: func(cmdObj *oscommands.CmdObj) {
assert.False(t, cmdObj.ShouldLog()) assert.False(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL) assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"}) assert.Equal(t, cmdObj.Args(), []string{"git", "fetch"})
@ -163,7 +163,7 @@ func TestSyncFetchBackground(t *testing.T) {
{ {
testName: "Fetch in background (all=true)", testName: "Fetch in background (all=true)",
fetchAllConfig: true, fetchAllConfig: true,
test: func(cmdObj oscommands.ICmdObj) { test: func(cmdObj *oscommands.CmdObj) {
assert.False(t, cmdObj.ShouldLog()) assert.False(t, cmdObj.ShouldLog())
assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL) assert.Equal(t, cmdObj.GetCredentialStrategy(), oscommands.FAIL)
assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"}) assert.Equal(t, cmdObj.Args(), []string{"git", "fetch", "--all"})

View file

@ -15,7 +15,7 @@ func NewTagCommands(gitCommon *GitCommon) *TagCommands {
} }
} }
func (self *TagCommands) CreateLightweightObj(tagName string, ref string, force bool) oscommands.ICmdObj { func (self *TagCommands) CreateLightweightObj(tagName string, ref string, force bool) *oscommands.CmdObj {
cmdArgs := NewGitCmd("tag"). cmdArgs := NewGitCmd("tag").
ArgIf(force, "--force"). ArgIf(force, "--force").
Arg("--", tagName). Arg("--", tagName).
@ -25,7 +25,7 @@ func (self *TagCommands) CreateLightweightObj(tagName string, ref string, force
return self.cmd.New(cmdArgs) return self.cmd.New(cmdArgs)
} }
func (self *TagCommands) CreateAnnotatedObj(tagName, ref, msg string, force bool) oscommands.ICmdObj { func (self *TagCommands) CreateAnnotatedObj(tagName, ref, msg string, force bool) *oscommands.CmdObj {
cmdArgs := NewGitCmd("tag").Arg(tagName). cmdArgs := NewGitCmd("tag").Arg(tagName).
ArgIf(force, "--force"). ArgIf(force, "--force").
ArgIf(len(ref) > 0, ref). ArgIf(len(ref) > 0, ref).

View file

@ -29,7 +29,7 @@ func NewWorkingTreeCommands(
} }
} }
func (self *WorkingTreeCommands) OpenMergeToolCmdObj() oscommands.ICmdObj { func (self *WorkingTreeCommands) OpenMergeToolCmdObj() *oscommands.CmdObj {
return self.cmd.New(NewGitCmd("mergetool").ToArgv()) return self.cmd.New(NewGitCmd("mergetool").ToArgv())
} }
@ -255,7 +255,7 @@ func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool,
return s return s
} }
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) oscommands.ICmdObj { func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) *oscommands.CmdObj {
colorArg := self.UserConfig().Git.Paging.ColorArg colorArg := self.UserConfig().Git.Paging.ColorArg
if plain { if plain {
colorArg = "never" colorArg = "never"
@ -293,7 +293,7 @@ func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bo
return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput() return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput()
} }
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) oscommands.ICmdObj { func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) *oscommands.CmdObj {
contextSize := self.AppState.DiffContextSize contextSize := self.AppState.DiffContextSize
colorArg := self.UserConfig().Git.Paging.ColorArg colorArg := self.UserConfig().Git.Paging.ColorArg

View file

@ -11,70 +11,6 @@ import (
// A command object is a general way to represent a command to be run on the // A command object is a general way to represent a command to be run on the
// command line. // command line.
type ICmdObj interface {
GetCmd() *exec.Cmd
// outputs string representation of command. Note that if the command was built
// using NewFromArgs, the output won't be quite the same as what you would type
// into a terminal e.g. 'sh -c git commit' as opposed to 'sh -c "git commit"'
ToString() string
// outputs args vector e.g. ["git", "commit", "-m", "my message"]
Args() []string
// Set a string to be used as stdin for the command.
SetStdin(input string) ICmdObj
AddEnvVars(...string) ICmdObj
GetEnvVars() []string
// sets the working directory
SetWd(string) ICmdObj
// runs the command and returns an error if any
Run() error
// runs the command and returns the output as a string, and an error if any
RunWithOutput() (string, error)
// runs the command and returns stdout and stderr as a string, and an error if any
RunWithOutputs() (string, string, error)
// runs the command and runs a callback function on each line of the output. If the callback returns true for the boolean value, we kill the process and return.
RunAndProcessLines(onLine func(line string) (bool, error)) error
// Be calling DontLog(), we're saying that once we call Run(), we don't want to
// log the command in the UI (it'll still be logged in the log file). The general rule
// is that if a command doesn't change the git state (e.g. read commands like `git diff`)
// then we don't want to log it. If we are changing something (e.g. `git add .`) then
// we do. The only exception is if we're running a command in the background periodically
// like `git fetch`, which technically does mutate stuff but isn't something we need
// to notify the user about.
DontLog() ICmdObj
// This returns false if DontLog() was called
ShouldLog() bool
// when you call this, then call Run(), we'll stream the output to the cmdWriter (i.e. the command log panel)
StreamOutput() ICmdObj
// returns true if StreamOutput() was called
ShouldStreamOutput() bool
// if you call this before ShouldStreamOutput we'll consider an error with no
// stderr content as a non-error. Not yet supported for Run or RunWithOutput (
// but adding support is trivial)
IgnoreEmptyError() ICmdObj
// returns true if IgnoreEmptyError() was called
ShouldIgnoreEmptyError() bool
PromptOnCredentialRequest(task gocui.Task) ICmdObj
FailOnCredentialRequest() ICmdObj
WithMutex(mutex *deadlock.Mutex) ICmdObj
Mutex() *deadlock.Mutex
GetCredentialStrategy() CredentialStrategy
GetTask() gocui.Task
Clone() ICmdObj
}
type CmdObj struct { type CmdObj struct {
cmd *exec.Cmd cmd *exec.Cmd
@ -112,12 +48,13 @@ const (
FAIL FAIL
) )
var _ ICmdObj = &CmdObj{}
func (self *CmdObj) GetCmd() *exec.Cmd { func (self *CmdObj) GetCmd() *exec.Cmd {
return self.cmd return self.cmd
} }
// outputs string representation of command. Note that if the command was built
// using NewFromArgs, the output won't be quite the same as what you would type
// into a terminal e.g. 'sh -c git commit' as opposed to 'sh -c "git commit"'
func (self *CmdObj) ToString() string { func (self *CmdObj) ToString() string {
// if a given arg contains a space, we need to wrap it in quotes // if a given arg contains a space, we need to wrap it in quotes
quotedArgs := lo.Map(self.cmd.Args, func(arg string, _ int) string { quotedArgs := lo.Map(self.cmd.Args, func(arg string, _ int) string {
@ -130,17 +67,19 @@ func (self *CmdObj) ToString() string {
return strings.Join(quotedArgs, " ") return strings.Join(quotedArgs, " ")
} }
// outputs args vector e.g. ["git", "commit", "-m", "my message"]
func (self *CmdObj) Args() []string { func (self *CmdObj) Args() []string {
return self.cmd.Args return self.cmd.Args
} }
func (self *CmdObj) SetStdin(input string) ICmdObj { // Set a string to be used as stdin for the command.
func (self *CmdObj) SetStdin(input string) *CmdObj {
self.cmd.Stdin = strings.NewReader(input) self.cmd.Stdin = strings.NewReader(input)
return self return self
} }
func (self *CmdObj) AddEnvVars(vars ...string) ICmdObj { func (self *CmdObj) AddEnvVars(vars ...string) *CmdObj {
self.cmd.Env = append(self.cmd.Env, vars...) self.cmd.Env = append(self.cmd.Env, vars...)
return self return self
@ -150,75 +89,95 @@ func (self *CmdObj) GetEnvVars() []string {
return self.cmd.Env return self.cmd.Env
} }
func (self *CmdObj) SetWd(wd string) ICmdObj { // sets the working directory
func (self *CmdObj) SetWd(wd string) *CmdObj {
self.cmd.Dir = wd self.cmd.Dir = wd
return self return self
} }
func (self *CmdObj) DontLog() ICmdObj { // By calling DontLog(), we're saying that once we call Run(), we don't want to
// log the command in the UI (it'll still be logged in the log file). The general rule
// is that if a command doesn't change the git state (e.g. read commands like `git diff`)
// then we don't want to log it. If we are changing something (e.g. `git add .`) then
// we do. The only exception is if we're running a command in the background periodically
// like `git fetch`, which technically does mutate stuff but isn't something we need
// to notify the user about.
func (self *CmdObj) DontLog() *CmdObj {
self.dontLog = true self.dontLog = true
return self return self
} }
// This returns false if DontLog() was called
func (self *CmdObj) ShouldLog() bool { func (self *CmdObj) ShouldLog() bool {
return !self.dontLog return !self.dontLog
} }
func (self *CmdObj) StreamOutput() ICmdObj { // when you call this, then call Run(), we'll stream the output to the cmdWriter (i.e. the command log panel)
func (self *CmdObj) StreamOutput() *CmdObj {
self.streamOutput = true self.streamOutput = true
return self return self
} }
// returns true if StreamOutput() was called
func (self *CmdObj) ShouldStreamOutput() bool { func (self *CmdObj) ShouldStreamOutput() bool {
return self.streamOutput return self.streamOutput
} }
func (self *CmdObj) IgnoreEmptyError() ICmdObj { // if you call this before ShouldStreamOutput we'll consider an error with no
// stderr content as a non-error. Not yet supported for Run or RunWithOutput (
// but adding support is trivial)
func (self *CmdObj) IgnoreEmptyError() *CmdObj {
self.ignoreEmptyError = true self.ignoreEmptyError = true
return self return self
} }
// returns true if IgnoreEmptyError() was called
func (self *CmdObj) ShouldIgnoreEmptyError() bool {
return self.ignoreEmptyError
}
func (self *CmdObj) Mutex() *deadlock.Mutex { func (self *CmdObj) Mutex() *deadlock.Mutex {
return self.mutex return self.mutex
} }
func (self *CmdObj) WithMutex(mutex *deadlock.Mutex) ICmdObj { func (self *CmdObj) WithMutex(mutex *deadlock.Mutex) *CmdObj {
self.mutex = mutex self.mutex = mutex
return self return self
} }
func (self *CmdObj) ShouldIgnoreEmptyError() bool { // runs the command and returns an error if any
return self.ignoreEmptyError
}
func (self *CmdObj) Run() error { func (self *CmdObj) Run() error {
return self.runner.Run(self) return self.runner.Run(self)
} }
// runs the command and returns the output as a string, and an error if any
func (self *CmdObj) RunWithOutput() (string, error) { func (self *CmdObj) RunWithOutput() (string, error) {
return self.runner.RunWithOutput(self) return self.runner.RunWithOutput(self)
} }
// runs the command and returns stdout and stderr as a string, and an error if any
func (self *CmdObj) RunWithOutputs() (string, string, error) { func (self *CmdObj) RunWithOutputs() (string, string, error) {
return self.runner.RunWithOutputs(self) return self.runner.RunWithOutputs(self)
} }
// runs the command and runs a callback function on each line of the output. If the callback
// returns true for the boolean value, we kill the process and return.
func (self *CmdObj) RunAndProcessLines(onLine func(line string) (bool, error)) error { func (self *CmdObj) RunAndProcessLines(onLine func(line string) (bool, error)) error {
return self.runner.RunAndProcessLines(self, onLine) return self.runner.RunAndProcessLines(self, onLine)
} }
func (self *CmdObj) PromptOnCredentialRequest(task gocui.Task) ICmdObj { func (self *CmdObj) PromptOnCredentialRequest(task gocui.Task) *CmdObj {
self.credentialStrategy = PROMPT self.credentialStrategy = PROMPT
self.task = task self.task = task
return self return self
} }
func (self *CmdObj) FailOnCredentialRequest() ICmdObj { func (self *CmdObj) FailOnCredentialRequest() *CmdObj {
self.credentialStrategy = FAIL self.credentialStrategy = FAIL
return self return self
@ -232,7 +191,7 @@ func (self *CmdObj) GetTask() gocui.Task {
return self.task return self.task
} }
func (self *CmdObj) Clone() ICmdObj { func (self *CmdObj) Clone() *CmdObj {
clone := &CmdObj{} clone := &CmdObj{}
*clone = *self *clone = *self
clone.cmd = cloneCmd(self.cmd) clone.cmd = cloneCmd(self.cmd)

View file

@ -11,11 +11,11 @@ import (
type ICmdObjBuilder interface { type ICmdObjBuilder interface {
// NewFromArgs takes a slice of strings like []string{"git", "commit"} and returns a new command object. // NewFromArgs takes a slice of strings like []string{"git", "commit"} and returns a new command object.
New(args []string) ICmdObj New(args []string) *CmdObj
// NewShell takes a string like `git commit` and returns an executable shell command for it e.g. `sh -c 'git commit'` // NewShell takes a string like `git commit` and returns an executable shell command for it e.g. `sh -c 'git commit'`
// shellFunctionsFile is an optional file path that will be sourced before executing the command. Callers should pass // shellFunctionsFile is an optional file path that will be sourced before executing the command. Callers should pass
// the value of UserConfig.OS.ShellFunctionsFile. // the value of UserConfig.OS.ShellFunctionsFile.
NewShell(commandStr string, shellFunctionsFile string) ICmdObj NewShell(commandStr string, shellFunctionsFile string) *CmdObj
// Quote wraps a string in quotes with any necessary escaping applied. The reason for bundling this up with the other methods in this interface is that we basically always need to make use of this when creating new command objects. // Quote wraps a string in quotes with any necessary escaping applied. The reason for bundling this up with the other methods in this interface is that we basically always need to make use of this when creating new command objects.
Quote(str string) string Quote(str string) string
} }
@ -28,13 +28,13 @@ type CmdObjBuilder struct {
// poor man's version of explicitly saying that struct X implements interface Y // poor man's version of explicitly saying that struct X implements interface Y
var _ ICmdObjBuilder = &CmdObjBuilder{} var _ ICmdObjBuilder = &CmdObjBuilder{}
func (self *CmdObjBuilder) New(args []string) ICmdObj { func (self *CmdObjBuilder) New(args []string) *CmdObj {
cmdObj := self.NewWithEnviron(args, os.Environ()) cmdObj := self.NewWithEnviron(args, os.Environ())
return cmdObj return cmdObj
} }
// A command with explicit environment from env // A command with explicit environment from env
func (self *CmdObjBuilder) NewWithEnviron(args []string, env []string) ICmdObj { func (self *CmdObjBuilder) NewWithEnviron(args []string, env []string) *CmdObj {
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...)
cmd.Env = env cmd.Env = env
@ -44,7 +44,7 @@ func (self *CmdObjBuilder) NewWithEnviron(args []string, env []string) ICmdObj {
} }
} }
func (self *CmdObjBuilder) NewShell(commandStr string, shellFunctionsFile string) ICmdObj { func (self *CmdObjBuilder) NewShell(commandStr string, shellFunctionsFile string) *CmdObj {
if len(shellFunctionsFile) > 0 { if len(shellFunctionsFile) > 0 {
commandStr = fmt.Sprintf("%ssource %s\n%s", self.platform.PrefixForShellFunctionsFile, shellFunctionsFile, commandStr) commandStr = fmt.Sprintf("%ssource %s\n%s", self.platform.PrefixForShellFunctionsFile, shellFunctionsFile, commandStr)
} }

View file

@ -15,10 +15,10 @@ import (
) )
type ICmdObjRunner interface { type ICmdObjRunner interface {
Run(cmdObj ICmdObj) error Run(cmdObj *CmdObj) error
RunWithOutput(cmdObj ICmdObj) (string, error) RunWithOutput(cmdObj *CmdObj) (string, error)
RunWithOutputs(cmdObj ICmdObj) (string, string, error) RunWithOutputs(cmdObj *CmdObj) (string, string, error)
RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error RunAndProcessLines(cmdObj *CmdObj, onLine func(line string) (bool, error)) error
} }
type cmdObjRunner struct { type cmdObjRunner struct {
@ -28,7 +28,7 @@ type cmdObjRunner struct {
var _ ICmdObjRunner = &cmdObjRunner{} var _ ICmdObjRunner = &cmdObjRunner{}
func (self *cmdObjRunner) Run(cmdObj ICmdObj) error { func (self *cmdObjRunner) Run(cmdObj *CmdObj) error {
if cmdObj.Mutex() != nil { if cmdObj.Mutex() != nil {
cmdObj.Mutex().Lock() cmdObj.Mutex().Lock()
defer cmdObj.Mutex().Unlock() defer cmdObj.Mutex().Unlock()
@ -46,7 +46,7 @@ func (self *cmdObjRunner) Run(cmdObj ICmdObj) error {
return err return err
} }
func (self *cmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) { func (self *cmdObjRunner) RunWithOutput(cmdObj *CmdObj) (string, error) {
if cmdObj.Mutex() != nil { if cmdObj.Mutex() != nil {
cmdObj.Mutex().Lock() cmdObj.Mutex().Lock()
defer cmdObj.Mutex().Unlock() defer cmdObj.Mutex().Unlock()
@ -71,7 +71,7 @@ func (self *cmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
return self.RunWithOutputAux(cmdObj) return self.RunWithOutputAux(cmdObj)
} }
func (self *cmdObjRunner) RunWithOutputs(cmdObj ICmdObj) (string, string, error) { func (self *cmdObjRunner) RunWithOutputs(cmdObj *CmdObj) (string, string, error) {
if cmdObj.Mutex() != nil { if cmdObj.Mutex() != nil {
cmdObj.Mutex().Lock() cmdObj.Mutex().Lock()
defer cmdObj.Mutex().Unlock() defer cmdObj.Mutex().Unlock()
@ -96,7 +96,7 @@ func (self *cmdObjRunner) RunWithOutputs(cmdObj ICmdObj) (string, string, error)
return self.RunWithOutputsAux(cmdObj) return self.RunWithOutputsAux(cmdObj)
} }
func (self *cmdObjRunner) RunWithOutputAux(cmdObj ICmdObj) (string, error) { func (self *cmdObjRunner) RunWithOutputAux(cmdObj *CmdObj) (string, error) {
self.log.WithField("command", cmdObj.ToString()).Debug("RunCommand") self.log.WithField("command", cmdObj.ToString()).Debug("RunCommand")
if cmdObj.ShouldLog() { if cmdObj.ShouldLog() {
@ -114,7 +114,7 @@ func (self *cmdObjRunner) RunWithOutputAux(cmdObj ICmdObj) (string, error) {
return output, err return output, err
} }
func (self *cmdObjRunner) RunWithOutputsAux(cmdObj ICmdObj) (string, string, error) { func (self *cmdObjRunner) RunWithOutputsAux(cmdObj *CmdObj) (string, string, error) {
self.log.WithField("command", cmdObj.ToString()).Debug("RunCommand") self.log.WithField("command", cmdObj.ToString()).Debug("RunCommand")
if cmdObj.ShouldLog() { if cmdObj.ShouldLog() {
@ -139,7 +139,7 @@ func (self *cmdObjRunner) RunWithOutputsAux(cmdObj ICmdObj) (string, string, err
return stdout, stderr, err return stdout, stderr, err
} }
func (self *cmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error { func (self *cmdObjRunner) RunAndProcessLines(cmdObj *CmdObj, onLine func(line string) (bool, error)) error {
if cmdObj.Mutex() != nil { if cmdObj.Mutex() != nil {
cmdObj.Mutex().Lock() cmdObj.Mutex().Lock()
defer cmdObj.Mutex().Unlock() defer cmdObj.Mutex().Unlock()
@ -190,7 +190,7 @@ func (self *cmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line st
return nil return nil
} }
func (self *cmdObjRunner) logCmdObj(cmdObj ICmdObj) { func (self *cmdObjRunner) logCmdObj(cmdObj *CmdObj) {
self.guiIO.logCommandFn(cmdObj.ToString(), true) self.guiIO.logCommandFn(cmdObj.ToString(), true)
} }
@ -213,7 +213,7 @@ type cmdHandler struct {
close func() error close func() error
} }
func (self *cmdObjRunner) runAndStream(cmdObj ICmdObj) error { func (self *cmdObjRunner) runAndStream(cmdObj *CmdObj) error {
return self.runAndStreamAux(cmdObj, func(handler *cmdHandler, cmdWriter io.Writer) { return self.runAndStreamAux(cmdObj, func(handler *cmdHandler, cmdWriter io.Writer) {
go func() { go func() {
_, _ = io.Copy(cmdWriter, handler.stdoutPipe) _, _ = io.Copy(cmdWriter, handler.stdoutPipe)
@ -222,7 +222,7 @@ func (self *cmdObjRunner) runAndStream(cmdObj ICmdObj) error {
} }
func (self *cmdObjRunner) runAndStreamAux( func (self *cmdObjRunner) runAndStreamAux(
cmdObj ICmdObj, cmdObj *CmdObj,
onRun func(*cmdHandler, io.Writer), onRun func(*cmdHandler, io.Writer),
) error { ) error {
cmdWriter := self.guiIO.newCmdWriterFn() cmdWriter := self.guiIO.newCmdWriterFn()
@ -297,7 +297,7 @@ var failPromptFn = func(CredentialType) <-chan string {
return ch return ch
} }
func (self *cmdObjRunner) runWithCredentialHandling(cmdObj ICmdObj) error { func (self *cmdObjRunner) runWithCredentialHandling(cmdObj *CmdObj) error {
promptFn, err := self.getCredentialPromptFn(cmdObj) promptFn, err := self.getCredentialPromptFn(cmdObj)
if err != nil { if err != nil {
return err return err
@ -306,7 +306,7 @@ func (self *cmdObjRunner) runWithCredentialHandling(cmdObj ICmdObj) error {
return self.runAndDetectCredentialRequest(cmdObj, promptFn) return self.runAndDetectCredentialRequest(cmdObj, promptFn)
} }
func (self *cmdObjRunner) getCredentialPromptFn(cmdObj ICmdObj) (func(CredentialType) <-chan string, error) { func (self *cmdObjRunner) getCredentialPromptFn(cmdObj *CmdObj) (func(CredentialType) <-chan string, error) {
switch cmdObj.GetCredentialStrategy() { switch cmdObj.GetCredentialStrategy() {
case PROMPT: case PROMPT:
return self.guiIO.promptForCredentialFn, nil return self.guiIO.promptForCredentialFn, nil
@ -322,7 +322,7 @@ func (self *cmdObjRunner) getCredentialPromptFn(cmdObj ICmdObj) (func(Credential
// promptUserForCredential is a function that gets executed when this function detect you need to fill in a password or passphrase // promptUserForCredential is a function that gets executed when this function detect you need to fill in a password or passphrase
// The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back // The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back
func (self *cmdObjRunner) runAndDetectCredentialRequest( func (self *cmdObjRunner) runAndDetectCredentialRequest(
cmdObj ICmdObj, cmdObj *CmdObj,
promptUserForCredential func(CredentialType) <-chan string, promptUserForCredential func(CredentialType) <-chan string,
) error { ) error {
// setting the output to english so we can parse it for a username/password request // setting the output to english so we can parse it for a username/password request

View file

@ -28,7 +28,7 @@ type FakeCmdObjRunner struct {
type CmdObjMatcher struct { type CmdObjMatcher struct {
description string description string
// returns true if the matcher matches the command object // returns true if the matcher matches the command object
test func(ICmdObj) bool test func(*CmdObj) bool
// output of the command // output of the command
output string output string
@ -48,12 +48,12 @@ func (self *FakeCmdObjRunner) remainingExpectedCmds() []CmdObjMatcher {
}) })
} }
func (self *FakeCmdObjRunner) Run(cmdObj ICmdObj) error { func (self *FakeCmdObjRunner) Run(cmdObj *CmdObj) error {
_, err := self.RunWithOutput(cmdObj) _, err := self.RunWithOutput(cmdObj)
return err return err
} }
func (self *FakeCmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) { func (self *FakeCmdObjRunner) RunWithOutput(cmdObj *CmdObj) (string, error) {
self.mutex.Lock() self.mutex.Lock()
defer self.mutex.Unlock() defer self.mutex.Unlock()
@ -78,12 +78,12 @@ func (self *FakeCmdObjRunner) RunWithOutput(cmdObj ICmdObj) (string, error) {
return "", nil return "", nil
} }
func (self *FakeCmdObjRunner) RunWithOutputs(cmdObj ICmdObj) (string, string, error) { func (self *FakeCmdObjRunner) RunWithOutputs(cmdObj *CmdObj) (string, string, error) {
output, err := self.RunWithOutput(cmdObj) output, err := self.RunWithOutput(cmdObj)
return output, "", err return output, "", err
} }
func (self *FakeCmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(line string) (bool, error)) error { func (self *FakeCmdObjRunner) RunAndProcessLines(cmdObj *CmdObj, onLine func(line string) (bool, error)) error {
output, err := self.RunWithOutput(cmdObj) output, err := self.RunWithOutput(cmdObj)
if err != nil { if err != nil {
return err return err
@ -105,7 +105,7 @@ func (self *FakeCmdObjRunner) RunAndProcessLines(cmdObj ICmdObj, onLine func(lin
return nil return nil
} }
func (self *FakeCmdObjRunner) ExpectFunc(description string, fn func(cmdObj ICmdObj) bool, output string, err error) *FakeCmdObjRunner { func (self *FakeCmdObjRunner) ExpectFunc(description string, fn func(cmdObj *CmdObj) bool, output string, err error) *FakeCmdObjRunner {
self.mutex.Lock() self.mutex.Lock()
defer self.mutex.Unlock() defer self.mutex.Unlock()
@ -121,7 +121,7 @@ func (self *FakeCmdObjRunner) ExpectFunc(description string, fn func(cmdObj ICmd
func (self *FakeCmdObjRunner) ExpectArgs(expectedArgs []string, output string, err error) *FakeCmdObjRunner { func (self *FakeCmdObjRunner) ExpectArgs(expectedArgs []string, output string, err error) *FakeCmdObjRunner {
description := fmt.Sprintf("matches args %s", strings.Join(expectedArgs, " ")) description := fmt.Sprintf("matches args %s", strings.Join(expectedArgs, " "))
self.ExpectFunc(description, func(cmdObj ICmdObj) bool { self.ExpectFunc(description, func(cmdObj *CmdObj) bool {
return slices.Equal(expectedArgs, cmdObj.GetCmd().Args) return slices.Equal(expectedArgs, cmdObj.GetCmd().Args)
}, output, err) }, output, err)
@ -130,7 +130,7 @@ func (self *FakeCmdObjRunner) ExpectArgs(expectedArgs []string, output string, e
func (self *FakeCmdObjRunner) ExpectGitArgs(expectedArgs []string, output string, err error) *FakeCmdObjRunner { func (self *FakeCmdObjRunner) ExpectGitArgs(expectedArgs []string, output string, err error) *FakeCmdObjRunner {
description := fmt.Sprintf("matches git args %s", strings.Join(expectedArgs, " ")) description := fmt.Sprintf("matches git args %s", strings.Join(expectedArgs, " "))
self.ExpectFunc(description, func(cmdObj ICmdObj) bool { self.ExpectFunc(description, func(cmdObj *CmdObj) bool {
return slices.Equal(expectedArgs, cmdObj.GetCmd().Args[1:]) return slices.Equal(expectedArgs, cmdObj.GetCmd().Args[1:])
}, output, err) }, output, err)

View file

@ -208,13 +208,13 @@ func (c *OSCommand) FileExists(path string) (bool, error) {
} }
// PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C // PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C
func (c *OSCommand) PipeCommands(cmdObjs ...ICmdObj) error { func (c *OSCommand) PipeCommands(cmdObjs ...*CmdObj) error {
cmds := lo.Map(cmdObjs, func(cmdObj ICmdObj, _ int) *exec.Cmd { cmds := lo.Map(cmdObjs, func(cmdObj *CmdObj, _ int) *exec.Cmd {
return cmdObj.GetCmd() return cmdObj.GetCmd()
}) })
logCmdStr := strings.Join( logCmdStr := strings.Join(
lo.Map(cmdObjs, func(cmdObj ICmdObj, _ int) string { lo.Map(cmdObjs, func(cmdObj *CmdObj, _ int) string {
return cmdObj.ToString() return cmdObj.ToString()
}), }),
" | ", " | ",

View file

@ -23,7 +23,7 @@ func NewGpgHelper(c *HelperCommon) *GpgHelper {
// WithWaitingStatus we get stuck there and can't return to lazygit. We could // WithWaitingStatus we get stuck there and can't return to lazygit. We could
// fix this bug, or just stop running subprocesses from within there, given that // fix this bug, or just stop running subprocesses from within there, given that
// we don't need to see a loading status if we're in a subprocess. // we don't need to see a loading status if we're in a subprocess.
func (self *GpgHelper) WithGpgHandling(cmdObj oscommands.ICmdObj, configKey git_commands.GpgConfigKey, waitingStatus string, onSuccess func() error, refreshScope []types.RefreshableView) error { func (self *GpgHelper) WithGpgHandling(cmdObj *oscommands.CmdObj, configKey git_commands.GpgConfigKey, waitingStatus string, onSuccess func() error, refreshScope []types.RefreshableView) error {
useSubprocess := self.c.Git().Config.NeedsGpgSubprocess(configKey) useSubprocess := self.c.Git().Config.NeedsGpgSubprocess(configKey)
if useSubprocess { if useSubprocess {
success, err := self.c.RunSubprocess(cmdObj) success, err := self.c.RunSubprocess(cmdObj)
@ -42,7 +42,7 @@ func (self *GpgHelper) WithGpgHandling(cmdObj oscommands.ICmdObj, configKey git_
} }
} }
func (self *GpgHelper) runAndStream(cmdObj oscommands.ICmdObj, waitingStatus string, onSuccess func() error, refreshScope []types.RefreshableView) error { func (self *GpgHelper) runAndStream(cmdObj *oscommands.CmdObj, waitingStatus string, onSuccess func() error, refreshScope []types.RefreshableView) error {
return self.c.WithWaitingStatus(waitingStatus, func(gocui.Task) error { return self.c.WithWaitingStatus(waitingStatus, func(gocui.Task) error {
if err := cmdObj.StreamOutput().Run(); err != nil { if err := cmdObj.StreamOutput().Run(); err != nil {
_ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: refreshScope}) _ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: refreshScope})

View file

@ -24,7 +24,7 @@ func NewTagsHelper(c *HelperCommon, commitsHelper *CommitsHelper, gpg *GpgHelper
func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error { func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error {
doCreateTag := func(tagName string, description string, force bool) error { doCreateTag := func(tagName string, description string, force bool) error {
var command oscommands.ICmdObj var command *oscommands.CmdObj
if description != "" || self.c.Git().Config.GetGpgTagSign() { if description != "" || self.c.Git().Config.GetGpgTagSign() {
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag) self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
command = self.c.Git().Tag.CreateAnnotatedObj(tagName, ref, description, force) command = self.c.Git().Tag.CreateAnnotatedObj(tagName, ref, description, force)

View file

@ -932,7 +932,7 @@ func (gui *Gui) checkForDeprecatedEditConfigs() {
} }
// returns whether command exited without error or not // returns whether command exited without error or not
func (gui *Gui) runSubprocessWithSuspenseAndRefresh(subprocess oscommands.ICmdObj) error { func (gui *Gui) runSubprocessWithSuspenseAndRefresh(subprocess *oscommands.CmdObj) error {
_, err := gui.runSubprocessWithSuspense(subprocess) _, err := gui.runSubprocessWithSuspense(subprocess)
if err != nil { if err != nil {
return err return err
@ -946,7 +946,7 @@ func (gui *Gui) runSubprocessWithSuspenseAndRefresh(subprocess oscommands.ICmdOb
} }
// returns whether command exited without error or not // returns whether command exited without error or not
func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool, error) { func (gui *Gui) runSubprocessWithSuspense(subprocess *oscommands.CmdObj) (bool, error) {
gui.Mutexes.SubprocessMutex.Lock() gui.Mutexes.SubprocessMutex.Lock()
defer gui.Mutexes.SubprocessMutex.Unlock() defer gui.Mutexes.SubprocessMutex.Unlock()
@ -970,7 +970,7 @@ func (gui *Gui) runSubprocessWithSuspense(subprocess oscommands.ICmdObj) (bool,
return true, nil return true, nil
} }
func (gui *Gui) runSubprocess(cmdObj oscommands.ICmdObj) error { //nolint:unparam func (gui *Gui) runSubprocess(cmdObj *oscommands.CmdObj) error { //nolint:unparam
gui.LogCommand(cmdObj.ToString(), true) gui.LogCommand(cmdObj.ToString(), true)
subprocess := cmdObj.GetCmd() subprocess := cmdObj.GetCmd()

View file

@ -34,11 +34,11 @@ func (self *guiCommon) PostRefreshUpdate(context types.Context) {
self.gui.postRefreshUpdate(context) self.gui.postRefreshUpdate(context)
} }
func (self *guiCommon) RunSubprocessAndRefresh(cmdObj oscommands.ICmdObj) error { func (self *guiCommon) RunSubprocessAndRefresh(cmdObj *oscommands.CmdObj) error {
return self.gui.runSubprocessWithSuspenseAndRefresh(cmdObj) return self.gui.runSubprocessWithSuspenseAndRefresh(cmdObj)
} }
func (self *guiCommon) RunSubprocess(cmdObj oscommands.ICmdObj) (bool, error) { func (self *guiCommon) RunSubprocess(cmdObj *oscommands.CmdObj) (bool, error) {
return self.gui.runSubprocessWithSuspense(cmdObj) return self.gui.runSubprocessWithSuspense(cmdObj)
} }

View file

@ -53,8 +53,8 @@ type IGuiCommon interface {
GetViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager GetViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager
// returns true if command completed successfully // returns true if command completed successfully
RunSubprocess(cmdObj oscommands.ICmdObj) (bool, error) RunSubprocess(cmdObj *oscommands.CmdObj) (bool, error)
RunSubprocessAndRefresh(oscommands.ICmdObj) error RunSubprocessAndRefresh(*oscommands.CmdObj) error
Context() IContextMgr Context() IContextMgr
ContextForKey(key ContextKey) Context ContextForKey(key ContextKey) Context