1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-11-25 22:32:13 +02:00

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
This commit is contained in:
Jesse Duffield
2023-07-09 21:09:52 +10:00
parent 8964cedf27
commit 6b9390409e
45 changed files with 333 additions and 222 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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