Skip to content

Commit 6dc2a15

Browse files
fetch default branch of a repo (#3)
* added check for main branch if master isn't found * added code to fetch default branch for a repo, changed execute method's signature to return command output * fixed main_test.go * changed regex to extract default branch and fixed main_test.go * added multiwriter for Stdout to capture response
1 parent 5b9c401 commit 6dc2a15

File tree

3 files changed

+94
-19
lines changed

3 files changed

+94
-19
lines changed

cmd-git.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,58 @@ package main
44

55
import (
66
"fmt"
7+
"regexp"
78
)
89

910
type gitRepo struct {
1011
url string
1112
dir string
1213
}
1314

14-
func gitCmd(args ...string) error {
15-
code := execute("git", args...)
15+
var re = regexp.MustCompile(`.*HEAD branch: (.*)\n`) // regex to extract default branch name of a repo
16+
17+
func gitCmd(args ...string) (string, error) {
18+
output, code := execute("git", args...)
1619
if code != 0 {
17-
return fmt.Errorf("git failed: exit code %d", code)
20+
return "", fmt.Errorf("git failed: exit code %d", code)
1821
}
19-
return nil
22+
return output, nil
2023
}
2124

2225
func gitOpenDir(url, dir string) (repo, error) {
23-
err := gitCmd("-C", dir, "rev-parse")
26+
_, err := gitCmd("-C", dir, "rev-parse")
2427
return &gitRepo{url: url, dir: dir}, err
2528
}
2629

2730
func gitCloneDir(url, dir string) (repo, error) {
28-
err := gitCmd("clone", "https://"+url, dir)
31+
_, err := gitCmd("clone", "https://"+url, dir)
2932
return &gitRepo{url: url, dir: dir}, err
3033
}
3134

3235
func (r *gitRepo) Checkout(rev string) error {
33-
if err := gitCmd("-C", r.dir, "checkout", "master"); err != nil {
36+
output, err := gitCmd("-C", r.dir, "remote", "show", "origin")
37+
if err != nil {
38+
return err
39+
}
40+
defaultBranch := extractBranch(output)
41+
if _, err := gitCmd("-C", r.dir, "checkout", defaultBranch); err != nil {
3442
return err
3543
}
3644
if rev == "" || rev == latestRev {
3745
rev = "HEAD"
3846
}
39-
return gitCmd("-C", r.dir, "checkout", "-q", rev)
47+
_, err = gitCmd("-C", r.dir, "checkout", "-q", rev)
48+
return err
4049
}
4150

4251
func (r *gitRepo) Fetch() error {
43-
return gitCmd("-C", r.dir, "pull")
52+
_, err := gitCmd("-C", r.dir, "pull")
53+
return err
54+
}
55+
56+
func extractBranch(output string) string {
57+
if !re.MatchString(output) {
58+
return "master"
59+
}
60+
return re.FindStringSubmatch(output)[1]
4461
}

main.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package main
22

33
import (
4+
"bytes"
45
"crypto/md5"
56
"errors"
67
"fmt"
8+
"io"
79
"io/ioutil"
810
"log"
911
"os"
@@ -179,20 +181,22 @@ func expandDirs(dirs []string) []string {
179181
}
180182

181183
// execute runs a command with the provided arguments, using current stdio, and
182-
// returns command exit status (zero on success).
183-
func execute(exe string, args ...string) int {
184+
// returns command output and exit status (zero on success).
185+
func execute(exe string, args ...string) (string, int) {
184186
cmd := exec.Command(exe, args...)
187+
var stdoutBuf bytes.Buffer
185188
cmd.Stdin = os.Stdin
186-
cmd.Stdout = os.Stdout
189+
cmd.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
187190
cmd.Stderr = os.Stderr
188191
if err := cmd.Run(); err != nil {
189192
if exitErr, ok := err.(*exec.ExitError); ok {
190193
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
191-
return status.ExitStatus()
194+
return "", status.ExitStatus()
192195
}
193196
}
194197
}
195-
return 0
198+
output := string(stdoutBuf.Bytes())
199+
return output, 0
196200
}
197201

198202
// cacheDir returns a path to the local user cache using XDG base directory
@@ -262,10 +266,11 @@ func runProtoc() int {
262266

263267
files = expandDirs(files)
264268
if len(files) == 0 {
265-
return execute(protocExePath, args...)
269+
_, err := execute(protocExePath, args...)
270+
return err
266271
}
267272
for _, f := range files {
268-
if exitCode := execute(protocExePath, append(args, f)...); exitCode != 0 {
273+
if _, exitCode := execute(protocExePath, append(args, f)...); exitCode != 0 {
269274
return exitCode
270275
}
271276
}

main_test.go

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"fmt"
45
"runtime"
56
"testing"
67
)
@@ -10,13 +11,65 @@ func TestExecute(t *testing.T) {
1011
t.Skip()
1112
}
1213

13-
if exit := execute("true"); exit != 0 {
14+
if _, exit := execute("true"); exit != 0 {
1415
t.Fatal(exit)
1516
}
16-
if exit := execute("false"); exit != 1 {
17+
if _, exit := execute("false"); exit != 1 {
1718
t.Fatal(exit)
1819
}
19-
if exit := execute("sh", "-c", "exit 42"); exit != 42 {
20+
if _, exit := execute("sh", "-c", "exit 42"); exit != 42 {
2021
t.Fatal(exit)
2122
}
2223
}
24+
func Test_extractBranchMaster(t *testing.T) {
25+
output := `* remote origin
26+
Fetch URL: git@github.com:foo/bar.git
27+
Push URL: git@github.com:foo/bar.git
28+
HEAD branch: master
29+
Remote branch:
30+
master tracked
31+
Local branch configured for 'git pull':
32+
master merges with remote master
33+
Local ref configured for 'git push':
34+
master pushes to master (up to date)
35+
`
36+
branch := extractBranch(output)
37+
if branch != "master" {
38+
t.Fatal("failed extracting branch")
39+
}
40+
}
41+
func Test_extractBranchMain(t *testing.T) {
42+
output := `* remote origin
43+
Fetch URL: git@github.com:foo/bar.git
44+
Push URL: git@github.com:foo/bar.git
45+
HEAD branch: main
46+
Remote branch:
47+
master tracked
48+
Local branch configured for 'git pull':
49+
master merges with remote master
50+
Local ref configured for 'git push':
51+
master pushes to master (up to date)
52+
`
53+
branch := extractBranch(output)
54+
fmt.Println("branch is ", branch)
55+
if branch != "main" {
56+
t.Fatal("failed extracting branch")
57+
}
58+
}
59+
func Test_extractBranchDefaultMasterBranch(t *testing.T) {
60+
output := `* remote origin
61+
Fetch URL: git@github.com:foo/bar.git
62+
Push URL: git@github.com:foo/bar.git
63+
HEAD branch:
64+
Remote branch:
65+
master tracked
66+
Local branch configured for 'git pull':
67+
master merges with remote master
68+
Local ref configured for 'git push':
69+
master pushes to master (up to date)
70+
`
71+
branch := extractBranch(output)
72+
if branch != "master" {
73+
t.Fatal("failed extracting branch")
74+
}
75+
}

0 commit comments

Comments
 (0)