-
Notifications
You must be signed in to change notification settings - Fork 0
/
processcommits.go
119 lines (99 loc) · 2.41 KB
/
processcommits.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
package superclog
import (
"bufio"
"fmt"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
"regexp"
"strings"
)
const (
ReleaseNoteTag = "#r"
)
var (
convCommitMatcher = regexp.MustCompile(`^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)\((.+)\): (.+$)`)
)
func GetCommits(path string, fromHash, toHash string) ([]Commit, error) {
r, err := git.PlainOpen(path)
if err != nil {
return nil, err
}
var to *object.Commit
if toHash == "" {
h, err := r.Head()
if err != nil {
return nil, err
}
if to, err = r.CommitObject(h.Hash()); err != nil {
return nil, err
}
} else {
if to, err = r.CommitObject(plumbing.NewHash(toHash)); err != nil {
return nil, err
}
}
from, err := r.CommitObject(plumbing.NewHash(fromHash))
if err != nil {
return nil, fmt.Errorf("from invalid: %w", err)
}
ancestor, err := from.IsAncestor(to)
if err != nil {
return nil, fmt.Errorf("is ancestor check: %w", err)
}
if !ancestor {
return nil, fmt.Errorf("%s is not ancestor of %s", toHash, fromHash)
}
// Commits reachable from the "to" hash
cIter, err := r.Log(&git.LogOptions{From: to.Hash})
if err != nil {
return nil, fmt.Errorf("log: %w", err)
}
commits := make([]Commit, 0, 16)
err = cIter.ForEach(func(c *object.Commit) error {
commits = append(commits, parseCommit(c))
if c.Hash.String() == fromHash {
return storer.ErrStop
}
return nil
})
if err != nil {
return nil, err
}
return commits, nil
}
func parseCommit(commit *object.Commit) Commit {
// Use scanner so we handle both cr and crlf
var lines []string
sc := bufio.NewScanner(strings.NewReader(commit.Message))
for sc.Scan() {
lines = append(lines, sc.Text())
}
hash := commit.Hash.String()
c := Commit{
Hash: hash,
ShortHash: hash[:7],
}
for i, line := range lines {
if i == 0 {
c.Message = line
c.Conventional = parseMessage(line)
}
if strings.HasPrefix(line, ReleaseNoteTag) {
c.ReleaseNote = strings.TrimSpace(strings.Replace(line, ReleaseNoteTag, "", 1))
}
}
return c
}
func parseMessage(message string) ConventionalCommit {
vals := convCommitMatcher.FindAllStringSubmatch(message, 3)
if len(vals) == 0 {
return ConventionalCommit{}
}
return ConventionalCommit{
Type: CategoryOf(vals[0][1]),
Component: vals[0][2],
Message: vals[0][3],
}
}