wip: add parseHeader function

This commit is contained in:
2020-10-31 18:24:55 +00:00
parent 5b086530ee
commit 67c89f0df1
3 changed files with 217 additions and 17 deletions

View File

@@ -3,11 +3,12 @@
package commit
type Commit struct {
Type string
Scope string
Description string
Body string
Footers []Footer
Type string
Scope string
Subject string
Body string
Footers []*Footer
IsBreaking bool
}
type Footer struct {

View File

@@ -1,21 +1,51 @@
package commit
import "bytes"
const (
cr = 13
lf = 10
import (
"bytes"
"errors"
"regexp"
)
func paragraphs(input []byte) [][]byte {
cln := bytes.ReplaceAll(input, []byte{cr, lf}, []byte{lf})
cln = bytes.ReplaceAll(cln, []byte{cr}, []byte{lf})
const (
cr = 13
lf = 10
crlf = "\r\n"
)
ps := bytes.Split(cln, []byte{lf, lf})
var rHeader = regexp.MustCompile(
`^([\w\-]*)(?:\(([\w\$\.\/\-\* ]*)\))?(!)?\: (.*)$`,
)
for i, p := range ps {
ps[i] = bytes.Trim(p, "\r\n")
func parseHeader(header []byte) (*Commit, error) {
if bytes.ContainsAny(header, crlf) {
return nil, errors.New("header cannot span multiple lines")
}
return ps
result := rHeader.FindSubmatch(header)
if result == nil {
return &Commit{Subject: string(header)}, nil
}
return &Commit{
Type: string(result[1]),
Scope: string(result[2]),
Subject: string(result[4]),
IsBreaking: (string(result[3]) == "!"),
}, nil
}
func paragraphs(input []byte) [][]byte {
paras := bytes.Split(normlizeLinefeeds(input), []byte{lf, lf})
for i, p := range paras {
paras[i] = bytes.Trim(p, crlf)
}
return paras
}
func normlizeLinefeeds(input []byte) []byte {
return bytes.ReplaceAll(
bytes.ReplaceAll(input, []byte{cr, lf}, []byte{lf}),
[]byte{cr}, []byte{lf},
)
}

View File

@@ -6,6 +6,175 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_parseHeader(t *testing.T) {
type args struct {
header []byte
}
tests := []struct {
name string
args args
want *Commit
errStr string
}{
{
name: "non-convention commit",
args: args{header: []byte("add user sorting option")},
want: &Commit{Subject: "add user sorting option"},
},
{
name: "type only",
args: args{header: []byte("feat: add user sorting option")},
want: &Commit{Type: "feat", Subject: "add user sorting option"},
},
{
name: "type and scope",
args: args{header: []byte("feat(user): add user sorting option")},
want: &Commit{
Type: "feat",
Scope: "user",
Subject: "add user sorting option",
},
},
{
name: "type and breaking",
args: args{header: []byte("feat!: add user sorting option")},
want: &Commit{
Type: "feat",
Subject: "add user sorting option",
IsBreaking: true,
},
},
{
name: "type, scope and breaking",
args: args{header: []byte("feat(user)!: add user sorting option")},
want: &Commit{
Type: "feat",
Scope: "user",
Subject: "add user sorting option",
IsBreaking: true,
},
},
{
name: "type with underscore (_)",
args: args{header: []byte("int_feat: add user sorting option")},
want: &Commit{
Type: "int_feat",
Subject: "add user sorting option",
},
},
{
name: "type with hyphen (-)",
args: args{header: []byte("int-feat: add user sorting option")},
want: &Commit{
Type: "int-feat",
Subject: "add user sorting option",
},
},
{
name: "scope with underscopre (_)",
args: args{
header: []byte("feat(user_sort): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user_sort",
Subject: "add user sorting option",
},
},
{
name: "scope with hyphen (-)",
args: args{
header: []byte("feat(user-sort): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user-sort",
Subject: "add user sorting option",
},
},
{
name: "scope with slash (/)",
args: args{
header: []byte("feat(user/sort): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user/sort",
Subject: "add user sorting option",
},
},
{
name: "scope with period (.)",
args: args{
header: []byte("feat(user.sort): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user.sort",
Subject: "add user sorting option",
},
},
{
name: "scope with dollar sign ($)",
args: args{
header: []byte("feat($user): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "$user",
Subject: "add user sorting option",
},
},
{
name: "scope with star (*)",
args: args{
header: []byte("feat(user*): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user*",
Subject: "add user sorting option",
},
},
{
name: "scope with space ( )",
args: args{
header: []byte("feat(user sort): add user sorting option"),
},
want: &Commit{
Type: "feat",
Scope: "user sort",
Subject: "add user sorting option",
},
},
{
name: "multi-line header (LF)",
args: args{
header: []byte("feat(user)!: add usersorting\noption"),
},
errStr: "header cannot span multiple lines",
},
{
name: "multi-line header (CR)",
args: args{
header: []byte("feat(user)!: add usersorting\roption"),
},
errStr: "header cannot span multiple lines",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseHeader(tt.args.header)
if tt.errStr != "" {
assert.Error(t, err, tt.errStr)
} else {
assert.Equal(t, tt.want, got)
}
})
}
}
func Test_paragraph(t *testing.T) {
type args struct {
input []byte