@@ -8,6 +8,22 @@ import (
88 "strings"
99)
1010
11+ // from https://github.com/conventional-commits/parser#the-grammar
12+
13+ // <header/summary> ::= <type>, "(", <scope>, ")", ["!"], ":", <whitespace>*, <text> <type>, ["!"], ":", <whitespace>*, <text>
14+ // <type> ::= <any UTF8-octets except newline or parens or ":" or "!:" or whitespace>+
15+ // <scope> ::= <any UTF8-octets except newline or parens>+
16+
17+ const (
18+ headRegExStr = `^(?P<type>[^\n\(\)(:|!:| )]+)(?:\((?P<scope>[^\n\(\)]+)\))?(?P<breaking>!)?: (?P<description>[^\n]+)(?:\n\s*\n(?P<body>(?:.|\n)*)(?:\n\s+\n(?P<footers>(?:[A-Za-z-]+: (?:.|\n)*)|(?:BREAKING CHANGE: (?:.|\n)*)|(?:[A-Za-z]+ \#(?:.|\n)*)))?)?$`
19+ footRegExStr = `^(?:(BREAKING[- ]CHANGE|(?:[A-Za-z-])+): |((?:[A-Za-z-])+) #)(.+)$`
20+ )
21+
22+ var (
23+ headerRegexp = regexp .MustCompile (headRegExStr )
24+ footerRegexp = regexp .MustCompile (footRegExStr )
25+ )
26+
1127var (
1228 errHeader = errors .New ("unable to parse commit header" )
1329 errNoNewLine = errors .New ("commit description not followed by an empty line" )
@@ -93,7 +109,6 @@ func Parse(message string) (*Commit, error) {
93109// parseLineAsFooter attempts to parse the given line as a footer, returning both the key and the value of the header.
94110// If the line cannot be parsed then both return values will be empty.
95111func parseLineAsFooter (line string ) (key , value string ) {
96- footerRegexp := regexp .MustCompile (`^(?:(BREAKING[- ]CHANGE|(?:[A-Za-z-])+): |((?:[A-Za-z-])+) #)(.+)$` )
97112 matches := footerRegexp .FindStringSubmatch (line )
98113 if len (matches ) != 4 {
99114 return "" , ""
@@ -107,14 +122,6 @@ func parseLineAsFooter(line string) (key, value string) {
107122
108123// parseHeader attempts to parse the commit description line and set the appropriate values in the the given commit
109124func parseHeader (header string , commit * Commit ) error {
110- // from https://github.com/conventional-commits/parser#the-grammar
111-
112- // <header/summary> ::= <type>, "(", <scope>, ")", ["!"], ":", <whitespace>*, <text> <type>, ["!"], ":", <whitespace>*, <text>
113- // <type> ::= <any UTF8-octets except newline or parens or ":" or "!:" or whitespace>+
114- // <scope> ::= <any UTF8-octets except newline or parens>+
115-
116- headerRegexp := regexp .MustCompile (`^(?P<type>[^\n\(\)(:|!:| )]+)(?:\((?P<scope>[^\n\(\)]+)\))?(?P<breaking>!)?: (?P<description>[^\n]+)(?:\n\s*\n(?P<body>(?:.|\n)*)(?:\n\s+\n(?P<footers>(?:[A-Za-z-]+: (?:.|\n)*)|(?:BREAKING CHANGE: (?:.|\n)*)|(?:[A-Za-z]+ \#(?:.|\n)*)))?)?$` )
117- // TODO: comma separated multiple scopes?
118125 matches := headerRegexp .FindStringSubmatch (header )
119126 if matches == nil {
120127 return errHeader
@@ -130,6 +137,7 @@ func parseHeader(header string, commit *Commit) error {
130137 case "type" :
131138 head .Type = match
132139 case "scope" :
140+ // TODO: comma separated multiple scopes?
133141 head .Scope = match
134142 case "description" :
135143 head .Description = match
@@ -142,7 +150,7 @@ func parseHeader(header string, commit *Commit) error {
142150 return nil
143151}
144152
145- // IsHeaderErr checks if given error is parser header error
153+ // IsHeaderErr checks if given error is header parse error
146154func IsHeaderErr (err error ) bool {
147155 return errors .Is (err , errHeader )
148156}
0 commit comments