From c789bba673da883af4d812a85819d6309c915f34 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 18 Sep 2018 21:32:24 +1000 Subject: color merged and unmerged commits differently --- pkg/commands/git.go | 35 ++++++++++++++++++++++++++++++----- pkg/commands/git_structs.go | 1 + 2 files changed, 31 insertions(+), 5 deletions(-) (limited to 'pkg/commands') diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 0c7509b91..cbf7aa2b8 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -462,23 +462,48 @@ func includesString(list []string, a string) bool { return false } +func (c *GitCommand) getMergeBase() string { + output, err := c.OSCommand.RunCommandWithOutput("git merge-base HEAD master") // TODO: support develop as well + if err != nil { + c.Log.Error("Could not get merge base") + return "" + } + return output +} + // GetCommits obtains the commits of the current branch func (c *GitCommand) GetCommits() []Commit { pushables := c.GetCommitsToPush() log := c.GetLog() - commits := []Commit{} // now we can split it up and turn it into commits lines := utils.SplitLines(log) - for _, line := range lines { + commits := make([]Commit, len(lines)) + for i, line := range lines { splitLine := strings.Split(line, " ") sha := splitLine[0] - pushed := includesString(pushables, sha) - commits = append(commits, Commit{ + pushed := !includesString(pushables, sha) + commits[i] = Commit{ Sha: sha, Name: strings.Join(splitLine[1:], " "), Pushed: pushed, DisplayString: strings.Join(splitLine, " "), - }) + } + } + commits = c.setCommitMergedStatuses(commits) + return commits +} + +func (c *GitCommand) setCommitMergedStatuses(commits []Commit) []Commit { + ancestor := c.getMergeBase() + if ancestor == "" { + return commits + } + passedAncestor := false + for i, commit := range commits { + if strings.HasPrefix(ancestor, commit.Sha) { + passedAncestor = true + } + commits[i].Merged = passedAncestor } return commits } diff --git a/pkg/commands/git_structs.go b/pkg/commands/git_structs.go index 2b3b3f2db..cb2d125fa 100644 --- a/pkg/commands/git_structs.go +++ b/pkg/commands/git_structs.go @@ -17,6 +17,7 @@ type Commit struct { Sha string Name string Pushed bool + Merged bool DisplayString string } -- cgit v1.2.3 From a2b3cd08234e933ed572f3d95d473e19bd6adc99 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Thu, 20 Sep 2018 09:48:56 +1000 Subject: add removeAll to git --- pkg/commands/git.go | 1 + 1 file changed, 1 insertion(+) (limited to 'pkg/commands') diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 5bc33b2f5..b394753ca 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -101,6 +101,7 @@ func NewGitCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer) Repo: repo, getGlobalGitConfig: gitconfig.Global, getLocalGitConfig: gitconfig.Local, + removeFile: os.RemoveAll, }, nil } -- cgit v1.2.3 From f3fc98a3d03756ec94bcad955eda268fddb3613a Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 25 Sep 2018 20:11:33 +1000 Subject: support git flow when colouring commits --- pkg/commands/git.go | 40 ++++++++++++++++++++++++++++------------ pkg/commands/git_test.go | 22 +++++++++++++++++++--- 2 files changed, 47 insertions(+), 15 deletions(-) (limited to 'pkg/commands') diff --git a/pkg/commands/git.go b/pkg/commands/git.go index b394753ca..0bfbc36a7 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -267,6 +267,10 @@ func (c *GitCommand) NewBranch(name string) error { return c.OSCommand.RunCommand(fmt.Sprintf("git checkout -b %s", name)) } +func (c *GitCommand) CurrentBranchName() (string, error) { + return c.OSCommand.RunCommandWithOutput("git symbolic-ref --short HEAD") +} + // DeleteBranch delete branch func (c *GitCommand) DeleteBranch(branch string, force bool) error { command := "git branch -d" @@ -460,17 +464,27 @@ func (c *GitCommand) GetBranchGraph(branchName string) (string, error) { return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git log --graph --color --abbrev-commit --decorate --date=relative --pretty=medium -100 %s", branchName)) } -func (c *GitCommand) getMergeBase() string { - output, err := c.OSCommand.RunCommandWithOutput("git merge-base HEAD master") // TODO: support develop as well +func (c *GitCommand) getMergeBase() (string, error) { + currentBranch, err := c.CurrentBranchName() if err != nil { - c.Log.Error("Could not get merge base") - return "" + return "", err + } + + baseBranch := "master" + if strings.HasPrefix(currentBranch, "feature/") { + baseBranch = "develop" } - return output + + output, err := c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git merge-base HEAD %s", baseBranch)) + if err != nil { + // swallowing error because it's not a big deal; probably because there are no commits yet + c.Log.Error(err) + } + return output, nil } // GetCommits obtains the commits of the current branch -func (c *GitCommand) GetCommits() []*Commit { +func (c *GitCommand) GetCommits() ([]*Commit, error) { pushables := c.GetCommitsToPush() log := c.GetLog() @@ -488,14 +502,16 @@ func (c *GitCommand) GetCommits() []*Commit { DisplayString: strings.Join(splitLine, " "), } } - commits = c.setCommitMergedStatuses(commits) - return commits + return c.setCommitMergedStatuses(commits) } -func (c *GitCommand) setCommitMergedStatuses(commits []*Commit) []*Commit { - ancestor := c.getMergeBase() +func (c *GitCommand) setCommitMergedStatuses(commits []*Commit) ([]*Commit, error) { + ancestor, err := c.getMergeBase() + if err != nil { + return nil, err + } if ancestor == "" { - return commits + return commits, nil } passedAncestor := false for i, commit := range commits { @@ -504,7 +520,7 @@ func (c *GitCommand) setCommitMergedStatuses(commits []*Commit) []*Commit { } commits[i].Merged = passedAncestor } - return commits + return commits, nil } // GetLog gets the git log (currently limited to 30 commits for performance diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 790a34690..e5faa707b 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1484,7 +1484,7 @@ func TestGitCommandGetCommits(t *testing.T) { type scenario struct { testName string command func(string, ...string) *exec.Cmd - test func([]*Commit) + test func([]*Commit, error) } scenarios := []scenario{ @@ -1500,11 +1500,18 @@ func TestGitCommandGetCommits(t *testing.T) { case "log": assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) return exec.Command("echo") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("test") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") } return nil }, - func(commits []*Commit) { + func(commits []*Commit, err error) { + assert.NoError(t, err) assert.Len(t, commits, 0) }, }, @@ -1520,23 +1527,32 @@ func TestGitCommandGetCommits(t *testing.T) { case "log": assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "78976bc") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") } return nil }, - func(commits []*Commit) { + func(commits []*Commit, err error) { + assert.NoError(t, err) assert.Len(t, commits, 2) assert.EqualValues(t, []*Commit{ { Sha: "8a2bb0e", Name: "commit 1", Pushed: true, + Merged: false, DisplayString: "8a2bb0e commit 1", }, { Sha: "78976bc", Name: "commit 2", Pushed: false, + Merged: true, DisplayString: "78976bc commit 2", }, }, commits) -- cgit v1.2.3 From fb9596a3fffa5c707b27fb0eee1768d76aefd206 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 25 Sep 2018 20:25:04 +1000 Subject: add test for getMergeBase --- pkg/commands/git_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'pkg/commands') diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 5a331ea18..d5b87a1f1 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1684,3 +1684,82 @@ func TestGitCommandDiff(t *testing.T) { }) } } + +func TestGitCommandGetMergeBase(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(string, error) + } + + scenarios := []scenario{ + { + "swallows an error if the call to merge-base returns an error", + 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 exec.Command("echo", "master") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("test") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.EqualValues(t, "", output) + }, + }, + { + "returns the commit when master", + 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 exec.Command("echo", "master") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "blah") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.Equal(t, "blah\n", output) + }, + }, + { + "checks against develop when a feature branch", + 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 exec.Command("echo", "feature/test") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "develop"}, args) + return exec.Command("echo", "blah") + } + return nil + }, + func(output string, err error) { + assert.NoError(t, err) + assert.Equal(t, "blah\n", output) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd := newDummyGitCommand() + gitCmd.OSCommand.command = s.command + s.test(gitCmd.getMergeBase()) + }) + } +} -- cgit v1.2.3 From eb69d98f99f77669ffbb8463f6f6d84441c638d4 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 25 Sep 2018 20:31:19 +1000 Subject: add test for CurrentBranchName --- pkg/commands/git.go | 6 +++++- pkg/commands/git_test.go | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'pkg/commands') diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 4d132237f..402ec3378 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -268,7 +268,11 @@ func (c *GitCommand) NewBranch(name string) error { } func (c *GitCommand) CurrentBranchName() (string, error) { - return c.OSCommand.RunCommandWithOutput("git symbolic-ref --short HEAD") + output, err := c.OSCommand.RunCommandWithOutput("git symbolic-ref --short HEAD") + if err != nil { + return "", err + } + return utils.TrimTrailingNewline(output), nil } // DeleteBranch delete branch diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index d5b87a1f1..a2b2b9524 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1763,3 +1763,15 @@ func TestGitCommandGetMergeBase(t *testing.T) { }) } } + +func TestGitCommandCurrentBranchName(t *testing.T) { + gitCmd := newDummyGitCommand() + gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { + assert.Equal(t, "git", cmd) + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + } + output, err := gitCmd.CurrentBranchName() + assert.Equal(t, "master", output) + assert.NoError(t, err) +} -- cgit v1.2.3 From 2be613679e2062fbb6916bf1a2ac97aebbcf9630 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 5 Oct 2018 09:11:19 +1000 Subject: more test coverage --- pkg/commands/git_test.go | 85 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'pkg/commands') diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index a2b2b9524..25820558a 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1570,6 +1570,34 @@ func TestGitCommandGetCommits(t *testing.T) { }, commits) }, }, + { + "GetCommits bubbles up an error from setCommitMergedStatuses", + func(cmd string, args ...string) *exec.Cmd { + assert.EqualValues(t, "git", cmd) + + switch args[0] { + case "rev-list": + assert.EqualValues(t, []string{"rev-list", "@{u}..head", "--abbrev-commit"}, args) + return exec.Command("echo", "8a2bb0e") + case "log": + assert.EqualValues(t, []string{"log", "--oneline", "-30"}, args) + return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2") + case "merge-base": + assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args) + return exec.Command("echo", "78976bc") + case "symbolic-ref": + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + // here's where we are returning the error + return exec.Command("test") + } + + return nil + }, + func(commits []*Commit, err error) { + assert.Error(t, err) + assert.Len(t, commits, 0) + }, + }, } for _, s := range scenarios { @@ -1753,6 +1781,16 @@ func TestGitCommandGetMergeBase(t *testing.T) { assert.Equal(t, "blah\n", output) }, }, + { + "bubbles up error if there is one", + func(cmd string, args ...string) *exec.Cmd { + return exec.Command("test") + }, + func(output string, err error) { + assert.Error(t, err) + assert.Equal(t, "", output) + }, + }, } for _, s := range scenarios { @@ -1765,13 +1803,44 @@ func TestGitCommandGetMergeBase(t *testing.T) { } func TestGitCommandCurrentBranchName(t *testing.T) { - gitCmd := newDummyGitCommand() - gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { - assert.Equal(t, "git", cmd) - assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) - return exec.Command("echo", "master") + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(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) + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("echo", "master") + }, + func(output string, err error) { + assert.NoError(t, err) + assert.EqualValues(t, "master", output) + }, + }, + { + "bubbles up error if there is one", + func(cmd string, args ...string) *exec.Cmd { + assert.Equal(t, "git", cmd) + assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args) + return exec.Command("test") + }, + func(output string, err error) { + assert.Error(t, err) + assert.EqualValues(t, "", output) + }, + }, + } + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd := newDummyGitCommand() + gitCmd.OSCommand.command = s.command + s.test(gitCmd.CurrentBranchName()) + }) } - output, err := gitCmd.CurrentBranchName() - assert.Equal(t, "master", output) - assert.NoError(t, err) } -- cgit v1.2.3