-
Notifications
You must be signed in to change notification settings - Fork 7
/
conventional.go
107 lines (94 loc) · 2.74 KB
/
conventional.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
package commitinfo
import (
"fmt"
"strings"
"github.com/lunarway/release-manager/internal/regexp"
"github.com/pkg/errors"
)
type ConventionalCommitInfo struct {
Message string
Description string
Fields []Field
}
type Field struct {
Name string
Value string
}
func NewField(name, value string) Field {
return Field{Name: name, Value: value}
}
func (i ConventionalCommitInfo) Field(name string) string {
for _, field := range i.Fields {
if field.Name == name {
return field.Value
}
}
return ""
}
func (i *ConventionalCommitInfo) SetField(name string, value string) {
for index, field := range i.Fields {
if field.Name == name {
i.Fields[index].Value = value
return
}
}
i.Fields = append(i.Fields, NewField(name, value))
}
func (i ConventionalCommitInfo) HasField(name string) bool {
for _, field := range i.Fields {
if field.Name == name {
return true
}
}
return false
}
func (i ConventionalCommitInfo) String() string {
var txts []string
if i.Message != "" {
txts = append(txts, i.Message)
}
if i.Description != "" {
if i.Message != "" {
txts = append(txts, i.Description)
}
}
var fieldLines []string
for _, field := range i.Fields {
fieldLines = append(fieldLines, fmt.Sprintf("%s: %s", field.Name, field.Value))
}
if len(fieldLines) > 0 {
txts = append(txts, strings.Join(fieldLines, "\n"))
}
return strings.Join(txts, "\n\n")
}
func ParseConventionalCommit(commitMessage string) (ConventionalCommitInfo, error) {
matches := conventionalCommitRegex.FindStringSubmatch(commitMessage)
if matches == nil {
return ConventionalCommitInfo{}, errors.Wrap(ErrNoMatch, "message does not match expected conventional commit structure")
}
message := strings.Trim(matches[conventionalCommitRegexLookup.Message], "\n")
description := strings.Trim(matches[conventionalCommitRegexLookup.Description], "\n")
fieldsText := strings.Trim(matches[conventionalCommitRegexLookup.Fields], "\n")
var fields []Field
if fieldsText != "" {
fieldLines := strings.Split(fieldsText, "\n")
for _, fieldLine := range fieldLines {
fieldParts := strings.SplitN(fieldLine, ":", 2)
if len(fieldParts) != 2 {
return ConventionalCommitInfo{}, fmt.Errorf("field line '%s' in commit could not be parsed", fieldLine)
}
fields = append(fields, NewField(fieldParts[0], strings.Trim(fieldParts[1], " ")))
}
}
return ConventionalCommitInfo{
Message: message,
Description: description,
Fields: fields,
}, nil
}
var conventionalCommitRegexLookup = struct {
Message int
Description int
Fields int
}{}
var conventionalCommitRegex = regexp.MustCompile(`(?s)^((?P<Message>[^\n]*)(?P<Description>.*?)((?P<Fields>(\n[a-zA-Z\-]+:[^\n]*)(\n[a-zA-Z\-]+:[^\n]*)*))?)?\n*$`, &conventionalCommitRegexLookup)