Skip to content

Commit cb3de18

Browse files
committed
feat: rough porting from python
a fast and rough porting version, from python to go.
1 parent ec0326a commit cb3de18

1 file changed

Lines changed: 143 additions & 0 deletions

File tree

commit-msg.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package main
2+
3+
import (
4+
"io/ioutil"
5+
"log"
6+
"os"
7+
"regexp"
8+
"strings"
9+
)
10+
11+
const (
12+
MERGE_PATTERN = `^Merge `
13+
HEADER_PATTERN = `^((fixup! |squash! )?(\w+)(?:\(([^\)\s]+)\))?: (.+))(?:\n|$)`
14+
LINE_LIMIT = 100
15+
BODY_REQUIRED = false
16+
)
17+
18+
var (
19+
typeList = [...]string{
20+
"feat", // 新功能(feature)
21+
"fix", // 修补bug
22+
"docs", // 文档(documentation)
23+
"style", // 格式(不影响代码运行的变动)
24+
"refactor", // 重构(既不是新增功能,也不是修改bug的代码变动)
25+
"perf", // 提升性能(performance)
26+
"test", // 增加测试
27+
"chore", // 构建过程或辅助工具的变动'
28+
"revert", // 撤销以前的 commit
29+
"Revert"} // 有些版本的工具生成的revert message首字母大写
30+
)
31+
32+
func getMsg(path string) string {
33+
if path == "" {
34+
log.Fatalln("Arg missing.")
35+
}
36+
37+
f, err := os.Stat(path)
38+
if err != nil {
39+
log.Fatalln(err)
40+
}
41+
42+
if f.IsDir() {
43+
log.Fatalln(path, "is not a file.")
44+
}
45+
46+
buf, err := ioutil.ReadFile(path)
47+
if err != nil {
48+
log.Fatalln(err)
49+
}
50+
51+
return string(buf)
52+
}
53+
54+
func checkEmpty(str string) bool {
55+
return strings.TrimSpace(str) == ""
56+
}
57+
58+
func checkType(type_ string) {
59+
for _, t := range typeList {
60+
if type_ == t {
61+
return
62+
}
63+
}
64+
log.Fatalln("Wrong type.")
65+
}
66+
67+
func checkHeader(header string) {
68+
if checkEmpty(header) {
69+
log.Fatalln("Empty header.")
70+
}
71+
72+
re := regexp.MustCompile(HEADER_PATTERN)
73+
groups := re.FindStringSubmatch(header)
74+
75+
isFixupOrSquash := (groups[2] != "")
76+
77+
type_ := groups[3]
78+
// scope = groups[4] // TODO: 根据配置对scope检查
79+
// subject = (groups[5] != "") // TODO: 根据规则对subject检查
80+
checkType(type_)
81+
82+
length := len(header)
83+
if length > LINE_LIMIT && !(isFixupOrSquash || type_ == "revert") {
84+
log.Fatalln("Line overlong.")
85+
}
86+
}
87+
88+
func checkBody(body string) {
89+
if checkEmpty(body) {
90+
if BODY_REQUIRED {
91+
log.Fatalln("Empty body.")
92+
} else {
93+
return
94+
}
95+
}
96+
97+
if !checkEmpty(strings.SplitN(body, "\n", 2)[0]) {
98+
log.Fatalln("Blank line lacking between header and body.")
99+
}
100+
101+
for _, line := range strings.Split(body, "\n") {
102+
if len(line) > LINE_LIMIT {
103+
log.Fatalln("Line overlong.")
104+
}
105+
}
106+
}
107+
108+
func validateMsg(msg string) {
109+
msg = strings.TrimSpace(msg)
110+
if msg == "" {
111+
log.Fatalln("Empty Message.")
112+
}
113+
114+
isMerge, err := regexp.MatchString(MERGE_PATTERN, msg)
115+
if err != nil {
116+
log.Fatalln(err)
117+
}
118+
119+
if isMerge {
120+
log.Println("Merge message, skip check.")
121+
os.Exit(0)
122+
}
123+
124+
sections := strings.SplitN(msg, "\n", 2)
125+
checkHeader(sections[0])
126+
127+
if len(sections) == 2 {
128+
checkBody(sections[1])
129+
} else if BODY_REQUIRED {
130+
log.Fatalln("Body missing. Maybe a new line is lacking.")
131+
}
132+
}
133+
134+
func main() {
135+
msgFile := ""
136+
if len(os.Args) > 1 {
137+
msgFile = os.Args[1]
138+
}
139+
140+
msg := getMsg(msgFile)
141+
142+
validateMsg(msg)
143+
}

0 commit comments

Comments
 (0)