-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhg.go
155 lines (125 loc) · 4.44 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
150
151
152
153
154
155
package vcsstate
import (
"errors"
"fmt"
"os/exec"
"strings"
)
var _, hgBinaryError = exec.LookPath("hg")
type hg struct{}
func (hg) Status(dir string) (string, error) {
cmd := exec.Command("hg", "status")
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", err
}
return string(out), nil
}
func (hg) Branch(dir string) (string, error) {
/* TODO: Detect and report detached head mode. This currently returns "default" even when in detached head mode.
Consider using `hg --debug identify` to resolve this. It might be helpful to detect detached head mode.
hg --debug identify
Print a summary identifying the repository state at REV using one or two parent hash identifiers,
followed by a "+" if the working directory has uncommitted changes, the branch name (if not default),
a list of tags, and a list of bookmarks.
65c40fd06bc50fdd6ded3a97b213f20d31428431
f5ac12b15e49095c60ae0acc6da0e28d47e2a29f+ tip
f5ac12b15e49095c60ae0acc6da0e28d47e2a29f tip
*/
cmd := exec.Command("hg", "branch")
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSuffix(string(out), "\n"), nil
}
// hgRevisionLength is the length of a Mercurial revision hash.
const hgRevisionLength = 40
func (hg) LocalRevision(dir string, defaultBranch string) (string, error) {
cmd := exec.Command("hg", "--debug", "identify", "-i", "--rev", defaultBranch)
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", err
}
if len(out) < hgRevisionLength {
return "", fmt.Errorf("output length %v is shorter than %v", len(out), hgRevisionLength)
}
return string(out[:hgRevisionLength]), nil
}
func (hg) Stash(dir string) (string, error) {
cmd := exec.Command("hg", "shelve", "--list")
cmd.Dir = dir
stdout, stderr, err := dividedOutput(cmd)
switch {
case err == nil && len(stdout) != 0:
return string(stdout), nil
case err == nil && len(stdout) == 0:
return "", nil
case err != nil && string(stderr) == "hg: unknown command 'shelve'\n":
return "", nil
default:
return "", err
}
}
func (hg) Contains(dir string, revision string, defaultBranch string) (bool, error) {
cmd := exec.Command("hg", "log", "--branch", defaultBranch, "--rev", revision)
cmd.Dir = dir
stdout, stderr, err := dividedOutput(cmd)
switch {
case err == nil && len(stdout) != 0:
return true, nil // Non-zero output means this commit is indeed contained.
case err == nil && len(stdout) == 0:
return false, nil // Zero output means this commit is not contained.
case err != nil && string(stderr) == fmt.Sprintf("abort: unknown revision '%s'!\n", revision):
return false, nil // Unknown revision error means this commit is not contained.
default:
return false, err
}
}
func (hg) RemoteContains(dir string, revision string, defaultBranch string) (bool, error) {
return false, errors.New("not implemented for hg")
}
func (hg) RemoteURL(dir string) (string, error) {
cmd := exec.Command("hg", "paths", "default")
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", err
}
return strings.TrimSuffix(string(out), "\n"), nil
}
func (hg) RemoteBranchAndRevision(dir string) (branch string, revision string, err error) {
// TODO: Query remote branch from actual remote; it's currently hardcoded to "default".
const defaultBranch = "default"
cmd := exec.Command("hg", "--debug", "identify", "-i", "--rev", defaultBranch, "default")
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return "", "", err
}
// Get the last line of output.
lines := strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") // lines will always contain at least one element.
return defaultBranch, lines[len(lines)-1], nil
}
func (hg) CachedRemoteDefaultBranch() (string, error) {
return "", fmt.Errorf("not implemented for hg, just use NoRemoteDefaultBranch")
}
func (hg) NoRemoteDefaultBranch() string {
return "default"
}
type remoteHg struct{}
func (remoteHg) RemoteBranchAndRevision(remoteURL string) (branch string, revision string, err error) {
// TODO: Query remote branch from actual remote; it's currently hardcoded to "default".
const defaultBranch = "default"
cmd := exec.Command("hg", "--debug", "identify", "-i", "--rev", defaultBranch, remoteURL)
out, err := cmd.Output()
if err != nil {
return "", "", err
}
// Get the last line of output.
lines := strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") // lines will always contain at least one element.
return defaultBranch, lines[len(lines)-1], nil
}