diff options
Diffstat (limited to 'pkg/commands')
-rw-r--r-- | pkg/commands/branches.go | 7 | ||||
-rw-r--r-- | pkg/commands/branches_test.go | 222 | ||||
-rw-r--r-- | pkg/commands/dummies.go | 9 | ||||
-rw-r--r-- | pkg/commands/files.go | 6 | ||||
-rw-r--r-- | pkg/commands/git.go | 8 | ||||
-rw-r--r-- | pkg/commands/loaders/branches.go | 26 | ||||
-rw-r--r-- | pkg/commands/loaders/commit_files.go | 57 | ||||
-rw-r--r-- | pkg/commands/loaders/commits.go | 15 | ||||
-rw-r--r-- | pkg/commands/loaders/commits_test.go | 2 | ||||
-rw-r--r-- | pkg/commands/loaders/files.go (renamed from pkg/commands/loading_files.go) | 40 | ||||
-rw-r--r-- | pkg/commands/loaders/files_test.go | 203 | ||||
-rw-r--r-- | pkg/commands/loading_commit_files.go | 43 | ||||
-rw-r--r-- | pkg/commands/loading_files_test.go | 227 | ||||
-rw-r--r-- | pkg/commands/oscommands/dummies.go | 2 | ||||
-rw-r--r-- | pkg/commands/oscommands/fake_cmd_obj_runner.go | 28 | ||||
-rw-r--r-- | pkg/commands/oscommands/os.go | 2 | ||||
-rw-r--r-- | pkg/commands/oscommands/os_test.go | 2 | ||||
-rw-r--r-- | pkg/commands/stash_entries.go | 11 |
18 files changed, 444 insertions, 466 deletions
diff --git a/pkg/commands/branches.go b/pkg/commands/branches.go index e3c40d343..ef1838e9e 100644 --- a/pkg/commands/branches.go +++ b/pkg/commands/branches.go @@ -127,9 +127,12 @@ type MergeOpts struct { // Merge merge func (c *GitCommand) Merge(branchName string, opts MergeOpts) error { - mergeArgs := c.UserConfig.Git.Merging.Args + mergeArg := "" + if c.UserConfig.Git.Merging.Args != "" { + mergeArg = " " + c.UserConfig.Git.Merging.Args + } - command := fmt.Sprintf("git merge --no-edit %s %s", mergeArgs, c.OSCommand.Quote(branchName)) + command := fmt.Sprintf("git merge --no-edit%s %s", mergeArg, c.OSCommand.Quote(branchName)) if opts.FastForwardOnly { command = fmt.Sprintf("%s --ff-only", command) } diff --git a/pkg/commands/branches_test.go b/pkg/commands/branches_test.go index 45cfb8315..58a3e1cc4 100644 --- a/pkg/commands/branches_test.go +++ b/pkg/commands/branches_test.go @@ -1,120 +1,85 @@ package commands import ( - "os/exec" "testing" - "github.com/jesseduffield/lazygit/pkg/secureexec" - "github.com/jesseduffield/lazygit/pkg/test" + "github.com/go-errors/errors" + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/stretchr/testify/assert" ) -// TestGitCommandGetCommitDifferences is a function. func TestGitCommandGetCommitDifferences(t *testing.T) { type scenario struct { - testName string - command func(string, ...string) *exec.Cmd - test func(string, string) + testName string + runner *oscommands.FakeCmdObjRunner + expectedPushables string + expectedPullables string } scenarios := []scenario{ { "Can't retrieve pushable count", - func(string, ...string) *exec.Cmd { - return secureexec.Command("test") - }, - func(pushableCount string, pullableCount string) { - assert.EqualValues(t, "?", pushableCount) - assert.EqualValues(t, "?", pullableCount) - }, + oscommands.NewFakeRunner(t). + Expect("git rev-list @{u}..HEAD --count", "", errors.New("error")), + "?", "?", }, { "Can't retrieve pullable count", - func(cmd string, args ...string) *exec.Cmd { - if args[1] == "HEAD..@{u}" { - return secureexec.Command("test") - } - - return secureexec.Command("echo") - }, - func(pushableCount string, pullableCount string) { - assert.EqualValues(t, "?", pushableCount) - assert.EqualValues(t, "?", pullableCount) - }, + oscommands.NewFakeRunner(t). + Expect("git rev-list @{u}..HEAD --count", "1\n", nil). + Expect("git rev-list HEAD..@{u} --count", "", errors.New("error")), + "?", "?", }, { "Retrieve pullable and pushable count", - func(cmd string, args ...string) *exec.Cmd { - if args[1] == "HEAD..@{u}" { - return secureexec.Command("echo", "10") - } - - return secureexec.Command("echo", "11") - }, - func(pushableCount string, pullableCount string) { - assert.EqualValues(t, "11", pushableCount) - assert.EqualValues(t, "10", pullableCount) - }, + oscommands.NewFakeRunner(t). + Expect("git rev-list @{u}..HEAD --count", "1\n", nil). + Expect("git rev-list HEAD..@{u} --count", "2\n", nil), + "1", "2", }, } for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = s.command - s.test(gitCmd.GetCommitDifferences("HEAD", "@{u}")) + gitCmd := NewDummyGitCommandWithRunner(s.runner) + pushables, pullables := gitCmd.GetCommitDifferences("HEAD", "@{u}") + assert.EqualValues(t, s.expectedPushables, pushables) + assert.EqualValues(t, s.expectedPullables, pullables) + s.runner.CheckForMissingCalls() }) } } -// TestGitCommandNewBranch is a function. func TestGitCommandNewBranch(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"checkout", "-b", "test", "master"}, args) - - return secureexec.Command("echo") - } + runner := oscommands.NewFakeRunner(t). + Expect(`git checkout -b "test" "master"`, "", nil) + gitCmd := NewDummyGitCommandWithRunner(runner) assert.NoError(t, gitCmd.NewBranch("test", "master")) + runner.CheckForMissingCalls() } -// TestGitCommandDeleteBranch is a function. func TestGitCommandDeleteBranch(t *testing.T) { type scenario struct { testName string - branch string force bool - command func(string, ...string) *exec.Cmd + runner *oscommands.FakeCmdObjRunner test func(error) } scenarios := []scenario{ { "Delete a branch", - "test", false, - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"branch", "-d", "test"}, args) - - return secureexec.Command("echo") - }, + oscommands.NewFakeRunner(t).Expect(`git branch -d "test"`, "", nil), func(err error) { assert.NoError(t, err) }, }, { "Force delete a branch", - "test", true, - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"branch", "-D", "test"}, args) - - return secureexec.Command("echo") - }, + oscommands.NewFakeRunner(t).Expect(`git branch -D "test"`, "", nil), func(err error) { assert.NoError(t, err) }, @@ -123,31 +88,27 @@ func TestGitCommandDeleteBranch(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = s.command - s.test(gitCmd.DeleteBranch(s.branch, s.force)) + gitCmd := NewDummyGitCommandWithRunner(s.runner) + + s.test(gitCmd.DeleteBranch("test", s.force)) + s.runner.CheckForMissingCalls() }) } } -// TestGitCommandMerge is a function. func TestGitCommandMerge(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"merge", "--no-edit", "test"}, args) - - return secureexec.Command("echo") - } + runner := oscommands.NewFakeRunner(t). + Expect(`git merge --no-edit "test"`, "", nil) + gitCmd := NewDummyGitCommandWithRunner(runner) assert.NoError(t, gitCmd.Merge("test", MergeOpts{})) + runner.CheckForMissingCalls() } -// TestGitCommandCheckout is a function. func TestGitCommandCheckout(t *testing.T) { type scenario struct { testName string - command func(string, ...string) *exec.Cmd + runner *oscommands.FakeCmdObjRunner test func(error) force bool } @@ -155,12 +116,7 @@ func TestGitCommandCheckout(t *testing.T) { scenarios := []scenario{ { "Checkout", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"checkout", "test"}, args) - - return secureexec.Command("echo") - }, + oscommands.NewFakeRunner(t).Expect(`git checkout "test"`, "", nil), func(err error) { assert.NoError(t, err) }, @@ -168,12 +124,7 @@ func TestGitCommandCheckout(t *testing.T) { }, { "Checkout forced", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"checkout", "--force", "test"}, args) - - return secureexec.Command("echo") - }, + oscommands.NewFakeRunner(t).Expect(`git checkout --force "test"`, "", nil), func(err error) { assert.NoError(t, err) }, @@ -183,52 +134,43 @@ func TestGitCommandCheckout(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = s.command + gitCmd := NewDummyGitCommandWithRunner(s.runner) s.test(gitCmd.Checkout("test", CheckoutOptions{Force: s.force})) + s.runner.CheckForMissingCalls() }) } } -// TestGitCommandGetBranchGraph is a function. func TestGitCommandGetBranchGraph(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"log", "--graph", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test", "--"}, args) - return secureexec.Command("echo") - } + runner := oscommands.NewFakeRunner(t).ExpectArgs([]string{ + "git", "log", "--graph", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", "test", "--", + }, "", nil) + gitCmd := NewDummyGitCommandWithRunner(runner) _, err := gitCmd.GetBranchGraph("test") assert.NoError(t, err) } func TestGitCommandGetAllBranchGraph(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"log", "--graph", "--all", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium"}, args) - return secureexec.Command("echo") - } + runner := oscommands.NewFakeRunner(t).ExpectArgs([]string{ + "git", "log", "--graph", "--all", "--color=always", "--abbrev-commit", "--decorate", "--date=relative", "--pretty=medium", + }, "", nil) + gitCmd := NewDummyGitCommandWithRunner(runner) cmdStr := gitCmd.UserConfig.Git.AllBranchesLogCmd _, err := gitCmd.Cmd.New(cmdStr).RunWithOutput() assert.NoError(t, err) } -// TestGitCommandCurrentBranchName is a function. func TestGitCommandCurrentBranchName(t *testing.T) { type scenario struct { testName string - command func(string, ...string) *exec.Cmd + runner *oscommands.FakeCmdObjRunner test func(string, string, error) } scenarios := []scenario{ { "says we are on the master branch if we are", - func(cmd string, args ...string) *exec.Cmd { - assert.Equal(t, "git", cmd) - return secureexec.Command("echo", "master") - }, + oscommands.NewFakeRunner(t).Expect(`git symbolic-ref --short HEAD`, "master", nil), func(name string, displayname string, err error) { assert.NoError(t, err) assert.EqualValues(t, "master", name) @@ -237,20 +179,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) { }, { "falls back to git `git branch --contains` if symbolic-ref fails", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return secureexec.Command("test") - case "branch": - assert.EqualValues(t, []string{"branch", "--contains"}, args) - return secureexec.Command("echo", "* master") - } - - return nil - }, + oscommands.NewFakeRunner(t). + Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")). + Expect(`git branch --contains`, "* master", nil), func(name string, displayname string, err error) { assert.NoError(t, err) assert.EqualValues(t, "master", name) @@ -259,20 +190,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) { }, { "handles a detached head", - func(cmd string, args ...string) *exec.Cmd { - assert.EqualValues(t, "git", cmd) - - switch args[0] { - case "symbolic-ref": - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return secureexec.Command("test") - case "branch": - assert.EqualValues(t, []string{"branch", "--contains"}, args) - return secureexec.Command("echo", "* (HEAD detached at 123abcd)") - } - - return nil - }, + oscommands.NewFakeRunner(t). + Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")). + Expect(`git branch --contains`, "* (HEAD detached at 123abcd)", nil), func(name string, displayname string, err error) { assert.NoError(t, err) assert.EqualValues(t, "123abcd", name) @@ -281,10 +201,9 @@ func TestGitCommandCurrentBranchName(t *testing.T) { }, { "bubbles up error if there is one", - func(cmd string, args ...string) *exec.Cmd { - assert.Equal(t, "git", cmd) - return secureexec.Command("test") - }, + oscommands.NewFakeRunner(t). + Expect(`git symbolic-ref --short HEAD`, "", errors.New("error")). + Expect(`git branch --contains`, "", errors.New("error")), func(name string, displayname string, err error) { assert.Error(t, err) assert.EqualValues(t, "", name) @@ -295,19 +214,18 @@ func TestGitCommandCurrentBranchName(t *testing.T) { for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd := NewDummyGitCommand() - gitCmd.OSCommand.Command = s.command + gitCmd := NewDummyGitCommandWithRunner(s.runner) s.test(gitCmd.CurrentBranchName()) + s.runner.CheckForMissingCalls() }) } } -// TestGitCommandResetHard is a function. func TestGitCommandResetHard(t *testing.T) { type scenario struct { testName string ref string - command func(string, ...string) *exec.Cmd + runner *oscommands.FakeCmdObjRunner test func(error) } @@ -315,23 +233,17 @@ func TestGitCommandResetHard(t *testing.T) { { "valid case", "HEAD", - test.CreateMockCommand(t, []*test.CommandSwapper{ - { - Expect: `git reset --hard HEAD`, - Replace: "echo", - }, - }), + oscommands.NewFakeRunner(t). + Expect(`git reset --hard "HEAD"`, "", nil), func(err error) { assert.NoError(t, err) }, }, } - gitCmd := NewDummyGitCommand() - for _, s := range scenarios { t.Run(s.testName, func(t *testing.T) { - gitCmd.OSCommand.Command = s.command + gitCmd := NewDummyGitCommandWithRunner(s.runner) s.test(gitCmd.ResetHard(s.ref)) }) } diff --git a/pkg/commands/dummies.go b/pkg/commands/dummies.go index c17179c8e..126007baa 100644 --- a/pkg/commands/dummies.go +++ b/pkg/commands/dummies.go @@ -23,3 +23,12 @@ func NewDummyGitCommandWithOSCommand(osCommand *oscommands.OSCommand) *GitComman GetCmdWriter: func() io.Writer { return ioutil.Discard }, } } + +func NewDummyGitCommandWithRunner(runner oscommands.ICmdObjRunner) *GitCommand { + builder := oscommands.NewDummyCmdObjBuilder(runner) + gitCommand := NewDummyGitCommand() + gitCommand.Cmd = builder + gitCommand.OSCommand.Cmd = builder + + return gitCommand +} diff --git a/pkg/commands/files.go b/pkg/commands/files.go index da451e80c..2d118c749 100644 --- a/pkg/commands/files.go +++ b/pkg/commands/files.go @@ -9,6 +9,7 @@ import ( "time" "github.com/go-errors/errors" + "github.com/jesseduffield/lazygit/pkg/commands/loaders" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/gui/filetree" @@ -75,7 +76,10 @@ func (c *GitCommand) BeforeAndAfterFileForRename(file *models.File) (*models.Fil // all files, passing the --no-renames flag and then recursively call the function // again for the before file and after file. - filesWithoutRenames := c.GetStatusFiles(GetStatusFileOptions{NoRenames: true}) + filesWithoutRenames := loaders. + NewFileLoader(c.Common, c.Cmd, c.GitConfig). + GetStatusFiles(loaders.GetStatusFileOptions{NoRenames: true}) + var beforeFile *models.File var afterFile *models.File for _, f := range filesWithoutRenames { diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 950042780..90fd7b262 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -223,3 +223,11 @@ func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filenam func VerifyInGitRepo(osCommand *oscommands.OSCommand) error { return osCommand.Cmd.New("git rev-parse --git-dir").Run() } + +func (c *GitCommand) GetDotGitDir() string { + return c.DotGitDir +} + +func (c *GitCommand) GetCmd() oscommands.ICmdObjBuilder { + return c.Cmd +} diff --git a/pkg/commands/loaders/branches.go b/pkg/commands/loaders/branches.go index fc3c15fc9..60e4f7aac 100644 --- a/pkg/commands/loaders/branches.go +++ b/pkg/commands/loaders/branches.go @@ -4,7 +4,6 @@ import ( "regexp" "strings" - "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/utils" @@ -29,9 +28,14 @@ type BranchLoader struct { reflogCommits []*models.Commit } +type BranchLoaderGitCommand interface { + GetRawBranches() (string, error) + CurrentBranchName() (string, string, error) +} + func NewBranchLoader( cmn *common.Common, - gitCommand *commands.GitCommand, + gitCommand BranchLoaderGitCommand, reflogCommits []*models.Commit, ) *BranchLoader { return &BranchLoader{ @@ -43,10 +47,10 @@ func NewBranchLoader( } // Load the list of branches for the current repo -func (b *BranchLoader) Load() []*models.Branch { - branches := b.obtainBranches() +func (self *BranchLoader) Load() []*models.Branch { + branches := self.obtainBranches() - reflogBranches := b.obtainReflogBranches() + reflogBranches := self.obtainReflogBranches() // loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches branchesWithRecency := make([]*models.Branch, 0) @@ -78,7 +82,7 @@ outer: } } if !foundHead { - currentBranchName, currentBranchDisplayName, err := b.getCurrentBranchName() + currentBranchName, currentBranchDisplayName, err := self.getCurrentBranchName() if err != nil { panic(err) } @@ -87,8 +91,8 @@ outer: return branches } -func (b *BranchLoader) obtainBranches() []*models.Branch { - output, err := b.getRawBranches() +func (self *BranchLoader) obtainBranches() []*models.Branch { + output, err := self.getRawBranches() if err != nil { panic(err) } @@ -150,11 +154,11 @@ func (b *BranchLoader) obtainBranches() []*models.Branch { // TODO: only look at the new reflog commits, and otherwise store the recencies in // int form against the branch to recalculate the time ago -func (b *BranchLoader) obtainReflogBranches() []*models.Branch { +func (self *BranchLoader) obtainReflogBranches() []*models.Branch { foundBranchesMap := map[string]bool{} re := regexp.MustCompile(`checkout: moving from ([\S]+) to ([\S]+)`) - reflogBranches := make([]*models.Branch, 0, len(b.reflogCommits)) - for _, commit := range b.reflogCommits { + reflogBranches := make([]*models.Branch, 0, len(self.reflogCommits)) + for _, commit := range self.reflogCommits { if match := re.FindStringSubmatch(commit.Name); len(match) == 3 { recency := utils.UnixToTimeAgo(commit.UnixTimestamp) for _, branchName := range match[1:] { diff --git a/pkg/commands/loaders/commit_files.go b/pkg/commands/loaders/commit_files.go new file mode 100644 index 000000000..1b65737ec --- /dev/null +++ b/pkg/commands/loaders/commit_files.go @@ -0,0 +1,57 @@ +package loaders + +import ( + "fmt" + "strings" + + "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" + "github.com/jesseduffield/lazygit/pkg/common" +) + +type CommitFileLoader struct { + *common.Common + cmd oscommands.ICmdObjBuilder +} + +func NewCommitFileLoader(common *common.Common, cmd oscommands.ICmdObjBuilder) *CommitFileLoader { + return &CommitFileLoader{ + Common: common, + cmd: cmd, + } +} + +// GetFilesInDiff get the specified commit files +func (self *CommitFileLoader) GetFilesInDiff(from string, to string, reverse bool) ([]*models.CommitFile, error) { + reverseFlag := "" + if reverse { + reverseFlag = " -R " + } + + filenames, err := self.cmd.New(fmt.Sprintf("git diff --submodule --no-ext-diff --name-status -z --no-renames %s %s %s", reverseFlag, from, to)).RunWithOutput() + if err != nil { + return nil, err + } + + return self.getCommitFilesFromFilenames(filenames), nil +} + +// filenames string is something like "file1\nfile2\nfile3" +func (self *CommitFileLoader) getCommitFilesFromFilenames(filenames string) []*models.CommitFile { + commitFiles := make([]*models.CommitFile, 0) + + lines := strings.Split(strings.TrimRight(filenames, "\x00"), "\x00") + n := len(lines) + for i := 0; i < n-1; i += 2 { + // typical result looks like 'A my_file' meaning my_file was added + changeStatus := lines[i] + name := lines[i+1] + + commitFiles = append(commitFiles, &models.CommitFile{ + Name: name, + ChangeStatus: changeStatus, + }) + } + + return commitFiles +} diff --git a/pkg/commands/loaders/commits.go b/pkg/commands/loaders/commits.go index bbd520c81..6f2336e3a 100644 --- a/pkg/commands/loaders/commits.go +++ b/pkg/commands/loaders/commits.go @@ -9,7 +9,6 @@ import ( "strconv" "strings" - "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/types/enums" @@ -37,20 +36,26 @@ type CommitLoader struct { dotGitDir string } +type CommitLoaderGitCommand interface { + CurrentBranchName() (string, string, error) + RebaseMode() (enums.RebaseMode, error) + GetCmd() oscommands.ICmdObjBuilder + GetDotGitDir() string +} + // making our dependencies explicit for the sake of easier testing func NewCommitLoader( cmn *common.Common, - gitCommand *commands.GitCommand, - osCommand *oscommands.OSCommand, + gitCommand CommitLoaderGitCommand, ) *CommitLoader { return &CommitLoader{ Common: cmn, - cmd: gitCommand.Cmd, + cmd: gitCommand.GetCmd(), getCurrentBranchName: gitCommand.CurrentBranchName, getRebaseMode: gitCommand.RebaseMode, readFile: ioutil.ReadFile, walkFiles: filepath.Walk, - dotGitDir: gitCommand.DotGitDir, + dotGitDir: gitCommand.GetDotGitDir(), } } diff --git a/pkg/commands/loaders/commits_test.go b/pkg/commands/loaders/commits_test.go index f793567f7..5491fb4a5 100644 --- a/pkg/commands/loaders/commits_test.go +++ b/pkg/commands/loaders/commits_test.go @@ -189,7 +189,7 @@ func TestGetCommits(t *testing.T) { t.Run(scenario.testName, func(t *testing.T) { builder := &CommitLoader{ Common: utils.NewDummyCommon(), - cmd: oscommands.NewCmdObjBuilderDummy(scenario.runner), + cmd: oscommands.NewDummyCmdObjBuilder(scenario.runner), getCurrentBranchName: func() (string, string, error) { return scenario.currentBranchName, scenario.currentBranchName, nil }, diff --git a/pkg/commands/loading_files.go b/pkg/commands/loaders/files.go index e28613c07..a1964a2b9 100644 --- a/pkg/commands/loading_files.go +++ b/pkg/commands/loaders/files.go @@ -1,36 +1,54 @@ -package commands +package loaders import ( "fmt" "strings" + "github.com/jesseduffield/lazygit/pkg/commands/git_config" "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" + "github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/utils" ) -// GetStatusFiles git status files +type FileLoader struct { + *common.Common + cmd oscommands.ICmdObjBuilder + gitConfig git_config.IGitConfig + getFileType func(string) string +} + +func NewFileLoader(cmn *common.Common, cmd oscommands.ICmdObjBuilder, gitConfig git_config.IGitConfig) *FileLoader { + return &FileLoader{ + Common: cmn, + cmd: cmd, + gitConfig: gitConfig, + getFileType: oscommands.FileType, + } +} + type GetStatusFileOptions struct { NoRenames bool } -func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File { +func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File { // check if config wants us ignoring untracked files - untrackedFilesSetting := c.GitConfig.Get("status.showUntrackedFiles") + untrackedFilesSetting := self.gitConfig.Get("status.showUntrackedFiles") if untrackedFilesSetting == "" { untrackedFilesSetting = "all" } untrackedFilesArg := fmt.Sprintf("--untracked-files=%s", untrackedFilesSetting) - statuses, err := c.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames, UntrackedFilesArg: untrackedFilesArg}) + statuses, err := self.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames, UntrackedFilesArg: untrackedFilesArg}) if err != nil { - c.Log.Error(err) + self.Log.Error(err) } files := []*models.File{} for _, status := range statuses { if strings.HasPrefix(status.StatusString, "warning") { - c.Log.Warningf("warning when calling git status: %s", status.StatusString) + self.Log.Warningf("warning when calling git status: %s", status.StatusString) continue } change := status.Change @@ -52,7 +70,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*models.File { Added: unstagedChange == "A" || untracked, HasMergeConflicts: hasMergeConflicts, HasInlineMergeConflicts: hasInlineMergeConflicts, - Type: c.OSCommand.FileType(status.Name), + Type: self.getFileType(status.Name), ShortStatus: change, } files = append(files, file) @@ -74,13 +92,13 @@ type FileStatus struct { PreviousName string } -func (c *GitCommand) GitStatus(opts GitStatusOptions) ([]FileStatus, error) { +func (c *FileLoader) GitStatus(opts GitStatusOptions) ([]FileStatus, error) { noRenamesFlag := "" if opts.NoRenames { - noRenamesFlag = "--no-renames" + noRenamesFlag = " --no-renames" } - statusLines, err := c.Cmd.New(fmt.Sprintf("git status %s --porcelain -z %s", opts.UntrackedFilesArg, noRenamesFlag)).RunWithOutput() + statusLines, err := c.cmd.New(fmt.Sprintf("git status %s --porcelain -z%s", opts.UntrackedFilesArg, noRenamesFlag)).RunWithOutput() if err != nil { return []FileStatus{}, err } diff --git a/pkg/commands/loaders/files_test.go b/pkg/commands/loaders/files_test.go new file mode 100644 index 000000000..1613290bb --- /dev/null +++ b/pkg/commands/loaders/files_test.go @@ -0,0 +1,203 @@ +package loaders + +import ( + "testing" + + "github.com/jesseduffield/lazygit/pkg/commands/git_config" + "github.com/jesseduffield/lazygit/pkg/commands/models" + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" + "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/stretchr/testify/assert" +) + +func TestGitCommandGetStatusFiles(t *testing.T) { + type scenario struct { + testName string + runner oscommands.ICmdObjRunner + expectedFiles []*models.File + } + + scenarios := []scenario{ + { + "No files found", + oscommands.NewFakeRunner(t). + Expect(`git status --untracked-files=yes --porcelain -z`, "", nil), + []*models.File{}, + }, + { + "Several files found", + oscommands.NewFakeRunner(t). + Expect( + `git status --untracked-files=yes --porcelain -z`, + "MM file1.txt\x00A file3.txt\x00AM file2.txt\x00?? file4.txt\x00UU file5.txt", + nil, + ), + []*models.File{ + { + Name: "file1.txt", + HasStagedChanges: true, + HasUnstagedChanges: true, + Tracked: true, + Added: false, + Deleted: false, + HasMergeConflicts: false, + HasInlineMergeConflicts: false, + DisplayString: "MM file1.txt", + Type: "file", + ShortStatus: "MM", + }, + { + Name: "file3.txt", + HasStagedChanges: true, + HasUnstagedChanges: false, + Tracked: false, + Added: true, + Deleted: false, + HasMergeConflicts: false, + HasInlineMergeConflicts: false, |