-
Notifications
You must be signed in to change notification settings - Fork 3
/
parser.go
96 lines (88 loc) · 1.95 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package gitprompt
import (
"bufio"
"bytes"
"errors"
"os/exec"
"strconv"
"strings"
)
// GitStatus is the parsed status for the current state in git.
type GitStatus struct {
Sha string
Branch string
Untracked int
Modified int
Staged int
Conflicts int
Ahead int
Behind int
}
// Parse parses the status for the repository from git. Returns nil if the
// current directory is not part of a git repository.
func Parse() (*GitStatus, error) {
status := &GitStatus{}
stat, err := runGitCommand("git", "status", "--branch", "--porcelain=2")
if err != nil {
if strings.HasPrefix(err.Error(), "fatal:") {
return nil, nil
}
return nil, err
}
lines := strings.Split(stat, "\n")
for _, line := range lines {
switch line[0] {
case '#':
parseHeader(line, status)
case '?':
status.Untracked++
case 'u':
status.Conflicts++
case '1', '2':
parts := strings.Split(line, " ")
if parts[1][0] != '.' {
status.Staged++
}
if parts[1][1] != '.' {
status.Modified++
}
}
}
return status, nil
}
func parseHeader(h string, s *GitStatus) {
if strings.HasPrefix(h, "# branch.oid") {
hash := h[13:]
if hash != "(initial)" {
s.Sha = hash
}
return
}
if strings.HasPrefix(h, "# branch.head") {
branch := h[14:]
if branch != "(detached)" {
s.Branch = branch
}
return
}
if strings.HasPrefix(h, "# branch.ab") {
parts := strings.Split(h, " ")
s.Ahead, _ = strconv.Atoi(strings.TrimPrefix(parts[2], "+"))
s.Behind, _ = strconv.Atoi(strings.TrimPrefix(parts[3], "-"))
return
}
}
func runGitCommand(cmd string, args ...string) (string, error) {
var stdout bytes.Buffer
var stderr bytes.Buffer
command := exec.Command(cmd, args...)
command.Stdout = bufio.NewWriter(&stdout)
command.Stderr = bufio.NewWriter(&stderr)
if err := command.Run(); err != nil {
if stderr.Len() > 0 {
return "", errors.New(stderr.String())
}
return "", err
}
return strings.TrimSpace(stdout.String()), nil
}