-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit.go
156 lines (130 loc) · 3.45 KB
/
git.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package vcsinfo
import (
"path/filepath"
"strings"
)
// GitProbe is a probe for extracting information out of a Git repository.
type GitProbe struct{}
// Name returns the human-facing name of the probe.
func (probe GitProbe) Name() string {
return "git"
}
// DefaultFormat returns the default format string to use for Git repositories.
func (probe GitProbe) DefaultFormat() string {
return "%n[%b%a%m%u%t]"
}
// IsAvailable indicates whether or not this probe has the tools/environment
// necessary to operate.
func (probe GitProbe) IsAvailable() (bool, error) {
return commandExists("git"), nil
}
// IsRepositoryRoot identifies whether or not the specified path is the root
// of a Git repository.
func (probe GitProbe) IsRepositoryRoot(path string) (bool, error) {
return dirExists(filepath.Join(path, ".git"))
}
func (probe GitProbe) extractStatus(path string, info *VcsInfo) error {
out, err := runCommand(path, "git", "status", "--porcelain")
if err != nil {
exitCode := getExitCode(err)
if exitCode == 128 && strings.Contains(out[0], "must be run in a work tree") {
return nil
}
return err
}
for _, line := range out {
index, work := line[0:1], line[1:2]
if index == "?" || work == "?" {
info.HasNew = true
} else {
if index != " " {
info.HasStaged = true
}
if work != " " {
info.HasModified = true
}
}
}
return nil
}
func (probe GitProbe) extractBranch(path string, info *VcsInfo) error {
out, err := runCommand(path, "git", "symbolic-ref", "--short", "HEAD")
if err != nil {
return err
}
info.Branch = out[0]
return nil
}
func (probe GitProbe) extractShortHash(path string, info *VcsInfo) error {
out, err := runCommand(path, "git", "rev-parse", "--short", "HEAD")
if err != nil {
exitCode := getExitCode(err)
if exitCode == 128 {
// This generally means the repo doesn't have a commit yet.
return nil
}
return err
}
info.ShortHash = out[0]
return nil
}
func (probe GitProbe) extractHash(path string, info *VcsInfo) error {
out, err := runCommand(path, "git", "rev-parse", "HEAD")
if err != nil {
exitCode := getExitCode(err)
if exitCode == 128 {
// This generally means the repo doesn't have a commit yet.
return nil
}
return err
}
info.Hash = out[0]
return nil
}
func (probe GitProbe) extractStashed(path string, info *VcsInfo) error {
out, err := runCommand(path, "git", "stash", "list")
if err != nil {
exitCode := getExitCode(err)
if exitCode == 1 && strings.Contains(out[0], "without a working tree") {
// This generally means the repo doesn't have a commit yet.
return nil
}
if exitCode == 128 && strings.Contains(out[0], "must be run in a work tree") {
return nil
}
return err
}
info.HasStashed = len(out) > 0
return nil
}
// GatherInfo extracts and returns VCS information for the Git repository at
// the specified path.
func (probe GitProbe) GatherInfo(path string) (VcsInfo, []error) {
info := VcsInfo{
VcsName: probe.Name(),
Path: path,
}
root, err := findAcceptablePath(path, probe.IsRepositoryRoot)
if err != nil {
return info, []error{err}
}
info.RepositoryRoot = root
errors := waitGroup(
func() error {
return probe.extractStatus(path, &info)
},
func() error {
return probe.extractBranch(path, &info)
},
func() error {
return probe.extractHash(path, &info)
},
func() error {
return probe.extractShortHash(path, &info)
},
func() error {
return probe.extractStashed(path, &info)
},
)
return info, errors
}