-
Notifications
You must be signed in to change notification settings - Fork 0
/
hg.go
149 lines (122 loc) · 3.25 KB
/
hg.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
package vcsinfo
import (
"path/filepath"
"strings"
)
// HgProbe is a probe for extracting information out of a Mercurial repository.
type HgProbe struct{}
// Name returns the human-facing name of the probe.
func (probe HgProbe) Name() string {
return "hg"
}
// DefaultFormat returns the default format string to use for Mercurial
// repositories.
func (probe HgProbe) DefaultFormat() string {
return "%n[%b%m%u%t]"
}
// IsAvailable indicates whether or not this probe has the tools/environment
// necessary to operate.
func (probe HgProbe) IsAvailable() (bool, error) {
return commandExists("hg"), nil
}
// IsRepositoryRoot identifies whether or not the specified path is the root
// of a Mercurial repository.
func (probe HgProbe) IsRepositoryRoot(path string) (bool, error) {
return dirExists(filepath.Join(path, ".hg"))
}
func runHgCommand(workingDir string, command ...string) ([]string, error) {
out, err := runCommand(workingDir, append([]string{"hg"}, command[0:]...)...)
filtered := make([]string, 0)
for _, line := range out {
if !strings.HasPrefix(line, "not trusting file") {
filtered = append(filtered, line)
}
}
return filtered, err
}
func (probe HgProbe) extractStatus(path string, info *VcsInfo) error {
out, err := runHgCommand(
path,
"status",
"--modified", "--added", "--removed", "--unknown", "--removed", "--deleted",
)
if err != nil {
return err
}
for _, line := range out {
if strings.HasPrefix(line, "?") {
info.HasNew = true
} else {
info.HasModified = true
}
}
return nil
}
func (probe HgProbe) extractCommitInfo(path string, info *VcsInfo) error {
out, err := runHgCommand(path, "identify", "--branch", "--num", "--id", "--debug")
if err != nil || len(out) == 0 {
return err
}
var parts []string
for _, line := range out {
parts = strings.Split(line, " ")
if len(parts) == 3 && parts[0] != "skip" {
break
}
}
if len(parts) != 3 {
return nil
}
info.Branch = parts[2]
if strings.HasPrefix(parts[0], "0000000000000000000000000000000000000000") {
return nil
}
info.Hash = parts[0]
if strings.HasSuffix(info.Hash, "+") {
info.Hash = info.Hash[0 : len(info.Hash)-1]
}
info.ShortHash = info.Hash[0:12]
info.Revision = parts[1]
if strings.HasSuffix(info.Revision, "+") {
info.Revision = info.Revision[0 : len(info.Revision)-1]
}
return nil
}
func (probe HgProbe) extractShelved(path string, info *VcsInfo) error {
out, err := runHgCommand(path, "shelve", "--list")
if err != nil {
exitCode := getExitCode(err)
if exitCode == 255 {
// This generally means the shelve extension isn't enabled.
return nil
}
return err
}
info.HasStashed = len(out) > 0
return nil
}
// GatherInfo extracts and returns VCS information for the Mercurial repository
// at the specified path.
func (probe HgProbe) 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.extractCommitInfo(path, &info)
},
func() error {
return probe.extractShelved(path, &info)
},
)
return info, errors
}