/
git.go
86 lines (74 loc) · 1.72 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
package stack
import (
"errors"
"fmt"
"regexp"
"strings"
)
func GitLog(env CmdEnv, args ...string) ([]*GitCommit, error) {
sep, err := randomSeparator()
if err != nil {
return nil, err
}
cmd := append([]string{"git", "log", "--pretty=%H" + sep + "%B" + sep}, args...)
out, err := env.Run(cmd...)
if err != nil {
return nil, err
}
out = strings.TrimSpace(out)
if out == "" {
return nil, nil
}
parts := strings.Split(out, sep)
var commits []*GitCommit
for i := 0; i < len(parts)-1; i += 2 {
hash := strings.TrimSpace(parts[i])
msg := strings.TrimSpace(parts[i+1])
uid, err := ParseCommitUID(msg)
if err != nil {
return nil, fmt.Errorf("%s: %w", hash, err)
}
commits = append(commits, &GitCommit{
Hash: hash,
UID: uid,
Message: msg,
})
}
return commits, nil
}
type GitCommit struct {
// Hash is the git commit hash.
Hash string
// UID is the value of the Commit-UID trailer.
UID string
// Message string
Message string
}
func (g GitCommit) Branch() string {
if g.UID == "" {
return ""
}
return "gh-stack-commit-" + g.UID
}
func (g GitCommit) Oneline() string {
return strings.Split(g.Message, "\n")[0]
}
func ParseCommitUID(input string) (string, error) {
commitPattern := regexp.MustCompile(`(?m)^Commit-UID:\s*(.*)$`)
matches := commitPattern.FindAllStringSubmatch(input, -1)
if matches == nil {
return "", nil
}
if len(matches) > 1 {
return "", errors.New("multiple Commit-UID trailers")
}
return matches[0][1], nil
}
func gitRootDir(c *Context) (string, error) {
s, err := c.cmd.Run("git", "rev-parse", "--show-toplevel")
return strings.TrimSpace(s), err
}
func gitFetch(c *Context) error {
_, err := c.cmd.Run("git", "fetch", c.config.RemoteName)
return err
}