--- a/exec/mock.go Wed Dec 27 23:20:33 2017 -0600
+++ b/exec/mock.go Thu Mar 08 12:52:20 2018 -0600
@@ -17,18 +17,48 @@
-type MockCommand struct {
+type MockResult struct { -func NewMockCommand(output string, err error) *MockCommand {
+func NewMockResult(stdout string, err error) *MockResult { + Stdout: []byte(stdout), +type MockCommand struct { +func NewMockCommand(results ...*MockResult) *MockCommand { - stdout: []byte(output),
func (c *MockCommand) Output() ([]byte, error) {
+ defer c.outputLock.Unlock() + if len(c.results) == 0 { + res := c.results[c.curResult] + if c.curResult < len(c.results)-1 { + return res.Stdout, res.Err --- a/git/git.go Wed Dec 27 23:20:33 2017 -0600
+++ b/git/git.go Thu Mar 08 12:52:20 2018 -0600
@@ -25,6 +25,21 @@
"bitbucket.org/rw_grim/govcs/vcs"
+func handleRevParseError(out string, err error) string { + // This handles the case where a user is in a git repo without any + // commits yet. Git returns an error as if it's outside the repo + // but still prints "HEAD" to stdout. + if err != nil && out == "HEAD" { // Git is an instance of vcs.VCS that will operate on a Git repository.
@@ -57,32 +72,55 @@
- return g.runCmd([]string{"config", "--local", "remote." + name + ".url"})
+ out, err := g.runCmd([]string{"config", "--local", "remote." + name + ".url"}) // Root will return the root of the repository.
func (g *Git) Root() string {
- return g.runCmd([]string{"rev-parse", "--show-toplevel"})
+ out, err := g.runCmd([]string{"rev-parse", "--show-toplevel"}) // Commit will return the commit id of the repository.
func (g *Git) Commit() string {
- return g.runCmd([]string{"rev-parse", "HEAD"})
+ out, err := g.runCmd([]string{"rev-parse", "HEAD"}) + return handleRevParseError(out, err) // ShortCommit returns the short commit id of the repository.
func (g *Git) ShortCommit() string {
- return g.runCmd([]string{"rev-parse", "--short", "HEAD"})
+ out, err := g.runCmd([]string{"rev-parse", "--short", "HEAD"}) + // If we can't get a short commit hash, try to get the full one. + // This is here to handle the case where a repo doesn't have any commits + // yet and returns a failure for the --short option but returns HEAD + // for the full commit id. // Branch returns the name of the checked out branch.
func (g *Git) Branch() string {
- return g.runCmd([]string{"rev-parse", "--abbrev-ref", "HEAD"})
+ out, err := g.runCmd([]string{"rev-parse", "--abbrev-ref", "HEAD"}) + return handleRevParseError(out, err) // Config will look up the given key and return a string slice of the values.
func (g *Git) Config(key string) []string {
- output := g.runCmd([]string{"config", key})
+ output, err := g.runCmd([]string{"config", key}) return strings.Split(output, "\n")
@@ -90,15 +128,12 @@
// runCmd will run the git command without the users config, it will also set
// working directory. All you need to pass in is a string slice of the
// subcommand that you want to run.
-func (g *Git) runCmd(cmdv []string) string {
+func (g *Git) runCmd(cmdv []string) (string, error) { os.Setenv("GIT_CONFIG_NOSYSTEM", "1")
args := append([]string{"-C", g.wd}, cmdv...)
cmd := exec.Command("git", args...)
output, err := cmd.Output()
- return strings.TrimSpace(string(output))
+ return strings.TrimSpace(string(output)), err --- a/git/git_test.go Wed Dec 27 23:20:33 2017 -0600
+++ b/git/git_test.go Thu Mar 08 12:52:20 2018 -0600
@@ -50,7 +50,7 @@
func (s *gitSuite) TestDetectFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("found", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("found", nil))) defer exec.SetBackend(backend)
vcs := Detect("working-directory")
@@ -62,7 +62,7 @@
func (s *gitSuite) TestDetectNotFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("", errors.New("not found")))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("", errors.New("not found")))) defer exec.SetBackend(backend)
@@ -70,7 +70,7 @@
func (s *gitSuite) TestRemoteEmpty(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("https://bitbucket.org/rw_grim/covcs\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("https://bitbucket.org/rw_grim/covcs\n", nil))) defer exec.SetBackend(backend)
@@ -79,7 +79,7 @@
func (s *gitSuite) TestRemoteNamed(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("https://bitbucket.org/rw_grim/covcs2\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("https://bitbucket.org/rw_grim/covcs2\n", nil))) defer exec.SetBackend(backend)
@@ -88,7 +88,7 @@
func (s *gitSuite) TestRoot(t sweet.T) {
path := "/home/foo/go/src/github.com/bar/baz"
- backend := s.setup(exec.NewMockCommand(path+"\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult(path+"\n", nil))) defer exec.SetBackend(backend)
@@ -96,15 +96,36 @@
func (s *gitSuite) TestCommit(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("deadbeef", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("deadbeef", nil))) defer exec.SetBackend(backend)
Expect(git.Commit()).To(Equal("deadbeef"))
+func (s *gitSuite) TestCommitOnEmptyRepo(t sweet.T) { + backend := s.setup(exec.NewMockCommand(exec.NewMockResult("HEAD", errors.New("exited")))) + defer exec.SetBackend(backend) + Expect(git.Commit()).To(Equal("HEAD")) +func (s *gitSuite) TestShortCommitOnEmptyRepo(t sweet.T) { + backend := s.setup(exec.NewMockCommand( + // Short commit returns an error and an empty output + exec.NewMockResult("", errors.New("exited")), + // We then call normal commit and that returns HEAD and an error + exec.NewMockResult("HEAD", errors.New("exited")), + defer exec.SetBackend(backend) + Expect(git.ShortCommit()).To(Equal("HEAD")) func (s *gitSuite) TestBranch(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("my-fancy-branch", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("my-fancy-branch", nil))) defer exec.SetBackend(backend)
@@ -112,7 +133,7 @@
func (s *gitSuite) TestConfigUserEmail(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("grim@reaperworld.com\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("grim@reaperworld.com\n", nil))) defer exec.SetBackend(backend)
--- a/govcs_test.go Wed Dec 27 23:20:33 2017 -0600
+++ b/govcs_test.go Thu Mar 08 12:52:20 2018 -0600
@@ -50,8 +50,10 @@
return exec.NewMockCommand(
- errors.New("not a "+cmdName+" repo"),
+ errors.New("not a "+cmdName+" repo"), @@ -59,7 +61,7 @@
func (s *vcsSuite) TestFindGitFromGit(t sweet.T) {
- backend := s.setup("git", exec.NewMockCommand("found", nil))
+ backend := s.setup("git", exec.NewMockCommand(exec.NewMockResult("found", nil))) defer exec.SetBackend(backend)
vcs, err := Detect("working-directory")
@@ -72,7 +74,7 @@
func (s *vcsSuite) TestFindHgFromHg(t sweet.T) {
- backend := s.setup("hg", exec.NewMockCommand("found", nil))
+ backend := s.setup("hg", exec.NewMockCommand(exec.NewMockResult("found", nil))) defer exec.SetBackend(backend)
vcs, err := Detect("working-directory")
@@ -85,7 +87,7 @@
func (s *vcsSuite) TestFindNoRepository(t sweet.T) {
- backend := s.setup("", exec.NewMockCommand("", errors.New("not a repo")))
+ backend := s.setup("", exec.NewMockCommand(exec.NewMockResult("", errors.New("not a repo")))) defer exec.SetBackend(backend)
vcs, err := Detect("working-directory")
--- a/hg/hg_test.go Wed Dec 27 23:20:33 2017 -0600
+++ b/hg/hg_test.go Thu Mar 08 12:52:20 2018 -0600
@@ -50,7 +50,7 @@
func (s *hgSuite) TestDetectFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("found", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("found", nil))) defer exec.SetBackend(backend)
vcs := Detect("working-directory")
@@ -62,7 +62,7 @@
func (s *hgSuite) TestDetectNotFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("", errors.New("not found")))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("", errors.New("not found")))) defer exec.SetBackend(backend)
@@ -70,7 +70,7 @@
func (s *hgSuite) TestRemoteEmpty(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("mypath\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("mypath\n", nil))) defer exec.SetBackend(backend)
@@ -79,7 +79,7 @@
func (s *hgSuite) TestRemoteNamed(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("myupstream\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("myupstream\n", nil))) defer exec.SetBackend(backend)
@@ -88,7 +88,7 @@
func (s *hgSuite) TestRoot(t sweet.T) {
path := "/home/foo/go/src/bitbucket.org/bar/baz"
- backend := s.setup(exec.NewMockCommand(path+"\n", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult(path+"\n", nil))) defer exec.SetBackend(backend)
@@ -96,7 +96,7 @@
func (s *hgSuite) TestCommit(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("deadbeef", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("deadbeef", nil))) defer exec.SetBackend(backend)
@@ -104,7 +104,7 @@
func (s *hgSuite) TestBranch(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("my-fancy-branch", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("my-fancy-branch", nil))) defer exec.SetBackend(backend)
@@ -112,7 +112,7 @@
func (s *hgSuite) TestBookmark(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("my-fancy-bookmark", nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("my-fancy-bookmark", nil))) defer exec.SetBackend(backend)
@@ -120,7 +120,9 @@
func (s *hgSuite) TestConfigPaths(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("paths.default=default\npaths.upstream=upstream\n", nil))
+ backend := s.setup(exec.NewMockCommand( + exec.NewMockResult("paths.default=default\npaths.upstream=upstream\n", nil), defer exec.SetBackend(backend)
--- a/svn/svn.go Wed Dec 27 23:20:33 2017 -0600
+++ b/svn/svn.go Thu Mar 08 12:52:20 2018 -0600
@@ -19,7 +19,6 @@
"bitbucket.org/rw_grim/govcs/exec"
@@ -52,7 +51,6 @@
- fmt.Printf("%#v\n", err)
@@ -105,7 +103,6 @@
err = xml.Unmarshal(output, &raw)
- fmt.Printf("rawSubversion: %#v\n", raw)
--- a/svn/svn_test.go Wed Dec 27 23:20:33 2017 -0600
+++ b/svn/svn_test.go Thu Mar 08 12:52:20 2018 -0600
@@ -77,7 +77,7 @@
func (s *svnSuite) TestDetectFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand(data, nil))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult(data, nil))) defer exec.SetBackend(backend)
vcs := Detect("working-directory")
@@ -95,7 +95,7 @@
func (s *svnSuite) TestDetectNotFound(t sweet.T) {
- backend := s.setup(exec.NewMockCommand("", errors.New("not found")))
+ backend := s.setup(exec.NewMockCommand(exec.NewMockResult("", errors.New("not found")))) defer exec.SetBackend(backend)