feat: show time of each commit as the default (#12)

* feat(git): add author time

* feat(git): add author info

* refactor: use commit option to generate convertional commit

* feat: add author date to convention commit

* refactor(changelog): replace t time var with when

Co-authored-by: Tran Hau <ngtranhau@gmail.com>
main
sudo pacman -Syu 2021-04-15 11:28:04 +07:00 committed by GitHub
parent 3ea63124fc
commit 552034123d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 120 additions and 45 deletions

View File

@ -19,7 +19,7 @@ const (
thirdLevel = 3
)
func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, version string, t time.Time) []markdown.Node {
func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, version string, when time.Time) []markdown.Node {
if len(commits) == 0 {
return nil
}
@ -72,7 +72,7 @@ func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, v
// Adding title, version to nodes
nodes = append([]markdown.Node{
markdown.NewHeader(firstLevel, title),
markdown.NewHeader(secondLevel, getVersionHeader(version, t)),
markdown.NewHeader(secondLevel, getVersionHeader(version, when)),
}, nodes...)
return nodes
@ -90,7 +90,7 @@ func ParseMarkdown(data string) []markdown.Node {
return nodes
}
func getVersionHeader(version string, t time.Time) string {
year, month, day := t.Date()
func getVersionHeader(version string, when time.Time) string {
year, month, day := when.Date()
return fmt.Sprintf("%s (%d-%d-%d)", version, year, month, day)
}

View File

@ -15,7 +15,7 @@ func TestGenerateMarkdown(t *testing.T) {
commits []convention.Commit
scopes map[string]struct{}
version string
t time.Time
when time.Time
}{
{
name: "empty old data",
@ -34,7 +34,7 @@ func TestGenerateMarkdown(t *testing.T) {
},
},
version: "v1.0.0",
t: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
when: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
},
{
name: "many commits",
@ -73,7 +73,7 @@ func TestGenerateMarkdown(t *testing.T) {
},
},
version: "v1.0.0",
t: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
when: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
},
{
name: "ignore commits outside scope",
@ -115,14 +115,14 @@ func TestGenerateMarkdown(t *testing.T) {
"a": struct{}{},
},
version: "v1.0.0",
t: time.Date(2020, 3, 22, 0, 0, 0, 0, time.Local),
when: time.Date(2020, 3, 22, 0, 0, 0, 0, time.Local),
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
g := goldie.New(t)
got := GenerateMarkdown(tc.commits, tc.scopes, tc.version, tc.t)
got := GenerateMarkdown(tc.commits, tc.scopes, tc.version, tc.when)
g.Assert(t, t.Name(), []byte(markdown.GenerateText(got)))
})
}

View File

@ -1,10 +1,6 @@
package convention
import (
"errors"
"regexp"
"strings"
"github.com/haunt98/changeloguru/pkg/git"
)
@ -13,12 +9,6 @@ import (
// [optional body]
// [optional footer(s)]
var (
headerRegex = regexp.MustCompile(`(?P<type>[a-zA-Z]+)(?P<scope>\([a-zA-Z]+\))?(?P<attention>!)?:\s(?P<description>.+)`)
ErrEmptyCommit = errors.New("empty commit")
)
// Commit represens conventional commit
type Commit struct {
// Commit as is
@ -29,28 +19,22 @@ type Commit struct {
}
// NewCommit return conventional commit from git commit
func NewCommit(c git.Commit) (result Commit, err error) {
// Preprocess
message := strings.TrimSpace(c.Message)
messages := strings.Split(message, "\n")
if len(messages) == 0 {
err = ErrEmptyCommit
return
}
func NewCommit(c git.Commit) (Commit, error) {
return NewCommitWithOptions(
GetRawHeader(c),
GetTypeAndScope(c),
AddAuthorDate(c),
)
}
// Use regex to detect
result.RawHeader = strings.TrimSpace(messages[0])
if !headerRegex.MatchString(result.RawHeader) {
result.Type = MiscType
return
// NewCommitWithOptions return conventional commit with custom option
func NewCommitWithOptions(opts ...OptionFn) (result Commit, err error) {
for _, opt := range opts {
if err = opt(&result); err != nil {
return
}
}
headerSubmatches := headerRegex.FindStringSubmatch(result.RawHeader)
result.Type = strings.ToLower(headerSubmatches[1])
result.Scope = strings.ToLower(headerSubmatches[2])
result.Scope = strings.TrimLeft(result.Scope, "(")
result.Scope = strings.TrimRight(result.Scope, ")")
return
}

View File

@ -2,6 +2,7 @@ package convention
import (
"testing"
"time"
"github.com/haunt98/changeloguru/pkg/git"
"github.com/sebdah/goldie/v2"
@ -50,6 +51,15 @@ func TestNewCommit(t *testing.T) {
Message: "random git message",
},
},
{
name: "Misc with author date",
c: git.Commit{
Message: "random git message",
Author: git.Author{
When: time.Date(2020, 4, 1, 0, 0, 0, 0, time.Local),
},
},
},
}
for _, tc := range tests {

59
pkg/convention/option.go Normal file
View File

@ -0,0 +1,59 @@
package convention
import (
"errors"
"fmt"
"regexp"
"strings"
"github.com/haunt98/changeloguru/pkg/git"
)
var (
ErrEmptyCommit = errors.New("empty commit")
headerRegex = regexp.MustCompile(`(?P<type>[a-zA-Z]+)(?P<scope>\([a-zA-Z]+\))?(?P<attention>!)?:\s(?P<description>.+)`)
)
type OptionFn func(*Commit) error
func GetRawHeader(gitCommit git.Commit) OptionFn {
return func(c *Commit) error {
message := strings.TrimSpace(gitCommit.Message)
messages := strings.Split(message, "\n")
if len(messages) == 0 {
return ErrEmptyCommit
}
c.RawHeader = messages[0]
return nil
}
}
func GetTypeAndScope(gitCommit git.Commit) OptionFn {
return func(c *Commit) error {
if !headerRegex.MatchString(c.RawHeader) {
c.Type = MiscType
return nil
}
headerSubmatches := headerRegex.FindStringSubmatch(c.RawHeader)
c.Type = strings.ToLower(headerSubmatches[1])
c.Scope = strings.ToLower(headerSubmatches[2])
c.Scope = strings.TrimLeft(c.Scope, "(")
c.Scope = strings.TrimRight(c.Scope, ")")
return nil
}
}
func AddAuthorDate(gitCommit git.Commit) OptionFn {
return func(c *Commit) error {
year, month, day := gitCommit.Author.When.Date()
c.RawHeader = fmt.Sprintf("%s (%d-%d-%d)", c.RawHeader, year, month, day)
return nil
}
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "docs: correct spelling of CHANGELOG",
"RawHeader": "docs: correct spelling of CHANGELOG (1-1-1)",
"Type": "docs",
"Scope": ""
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "refactor!: drop support for Node 6",
"RawHeader": "refactor!: drop support for Node 6 (1-1-1)",
"Type": "refactor",
"Scope": ""
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "feat(lang): add polish language",
"RawHeader": "feat(lang): add polish language (1-1-1)",
"Type": "feat",
"Scope": "lang"
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "random git message",
"RawHeader": "random git message (1-1-1)",
"Type": "misc",
"Scope": ""
}

View File

@ -0,0 +1,5 @@
{
"RawHeader": "random git message (2020-4-1)",
"Type": "misc",
"Scope": ""
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "Docs: correct spelling of CHANGELOG",
"RawHeader": "Docs: correct spelling of CHANGELOG (1-1-1)",
"Type": "docs",
"Scope": ""
}

View File

@ -1,5 +1,5 @@
{
"RawHeader": "REFACTOR!: drop support for Node 6",
"RawHeader": "REFACTOR!: drop support for Node 6 (1-1-1)",
"Type": "refactor",
"Scope": ""
}

9
pkg/git/author.go Normal file
View File

@ -0,0 +1,9 @@
package git
import "time"
type Author struct {
Name string
Email string
When time.Time
}

View File

@ -1,15 +1,23 @@
package git
import "github.com/go-git/go-git/v5/plumbing/object"
import (
"github.com/go-git/go-git/v5/plumbing/object"
)
// Commit stores all git-commit information
type Commit struct {
Message string
Author Author
}
// Convert from git-commit
func newCommit(commit *object.Commit) Commit {
return Commit{
Message: commit.Message,
Author: Author{
Name: commit.Author.Name,
Email: commit.Author.Email,
When: commit.Author.When,
},
}
}