From 552034123d5349909bb0bec80be04b62fc087ab3 Mon Sep 17 00:00:00 2001 From: Nguyen Tran Hau Date: Thu, 15 Apr 2021 11:28:04 +0700 Subject: [PATCH] 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 --- pkg/changelog/markdown.go | 8 +-- pkg/changelog/markdown_test.go | 10 ++-- pkg/convention/commit.go | 42 ++++--------- pkg/convention/commit_test.go | 10 ++++ pkg/convention/option.go | 59 +++++++++++++++++++ .../Commit_message_with_no_body.golden | 2 +- ...o_draw_attention_to_breaking_change.golden | 2 +- .../Commit_message_with_scope.golden | 2 +- .../testdata/TestNewCommit/Misc.golden | 2 +- .../Misc_with_author_date.golden | 5 ++ .../testdata/TestNewCommit/Mixedcase.golden | 2 +- .../testdata/TestNewCommit/Uppercase.golden | 2 +- pkg/git/author.go | 9 +++ pkg/git/commit.go | 10 +++- 14 files changed, 120 insertions(+), 45 deletions(-) create mode 100644 pkg/convention/option.go create mode 100644 pkg/convention/testdata/TestNewCommit/Misc_with_author_date.golden create mode 100644 pkg/git/author.go diff --git a/pkg/changelog/markdown.go b/pkg/changelog/markdown.go index cdef66b..a1e786e 100644 --- a/pkg/changelog/markdown.go +++ b/pkg/changelog/markdown.go @@ -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) } diff --git a/pkg/changelog/markdown_test.go b/pkg/changelog/markdown_test.go index edf963a..b91a701 100644 --- a/pkg/changelog/markdown_test.go +++ b/pkg/changelog/markdown_test.go @@ -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))) }) } diff --git a/pkg/convention/commit.go b/pkg/convention/commit.go index 928083a..6c3225c 100644 --- a/pkg/convention/commit.go +++ b/pkg/convention/commit.go @@ -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[a-zA-Z]+)(?P\([a-zA-Z]+\))?(?P!)?:\s(?P.+)`) - - 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 } diff --git a/pkg/convention/commit_test.go b/pkg/convention/commit_test.go index f1b0c94..8a4d0d2 100644 --- a/pkg/convention/commit_test.go +++ b/pkg/convention/commit_test.go @@ -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 { diff --git a/pkg/convention/option.go b/pkg/convention/option.go new file mode 100644 index 0000000..9ec9cd6 --- /dev/null +++ b/pkg/convention/option.go @@ -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[a-zA-Z]+)(?P\([a-zA-Z]+\))?(?P!)?:\s(?P.+)`) +) + +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 + } +} diff --git a/pkg/convention/testdata/TestNewCommit/Commit_message_with_no_body.golden b/pkg/convention/testdata/TestNewCommit/Commit_message_with_no_body.golden index 7486b3a..f35f53d 100644 --- a/pkg/convention/testdata/TestNewCommit/Commit_message_with_no_body.golden +++ b/pkg/convention/testdata/TestNewCommit/Commit_message_with_no_body.golden @@ -1,5 +1,5 @@ { - "RawHeader": "docs: correct spelling of CHANGELOG", + "RawHeader": "docs: correct spelling of CHANGELOG (1-1-1)", "Type": "docs", "Scope": "" } \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Commit_message_with_not_character_to_draw_attention_to_breaking_change.golden b/pkg/convention/testdata/TestNewCommit/Commit_message_with_not_character_to_draw_attention_to_breaking_change.golden index 3039035..e6e9938 100644 --- a/pkg/convention/testdata/TestNewCommit/Commit_message_with_not_character_to_draw_attention_to_breaking_change.golden +++ b/pkg/convention/testdata/TestNewCommit/Commit_message_with_not_character_to_draw_attention_to_breaking_change.golden @@ -1,5 +1,5 @@ { - "RawHeader": "refactor!: drop support for Node 6", + "RawHeader": "refactor!: drop support for Node 6 (1-1-1)", "Type": "refactor", "Scope": "" } \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Commit_message_with_scope.golden b/pkg/convention/testdata/TestNewCommit/Commit_message_with_scope.golden index 8b35ada..f6dd9c0 100644 --- a/pkg/convention/testdata/TestNewCommit/Commit_message_with_scope.golden +++ b/pkg/convention/testdata/TestNewCommit/Commit_message_with_scope.golden @@ -1,5 +1,5 @@ { - "RawHeader": "feat(lang): add polish language", + "RawHeader": "feat(lang): add polish language (1-1-1)", "Type": "feat", "Scope": "lang" } \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Misc.golden b/pkg/convention/testdata/TestNewCommit/Misc.golden index c005429..a9ff8b0 100644 --- a/pkg/convention/testdata/TestNewCommit/Misc.golden +++ b/pkg/convention/testdata/TestNewCommit/Misc.golden @@ -1,5 +1,5 @@ { - "RawHeader": "random git message", + "RawHeader": "random git message (1-1-1)", "Type": "misc", "Scope": "" } \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Misc_with_author_date.golden b/pkg/convention/testdata/TestNewCommit/Misc_with_author_date.golden new file mode 100644 index 0000000..47df7e2 --- /dev/null +++ b/pkg/convention/testdata/TestNewCommit/Misc_with_author_date.golden @@ -0,0 +1,5 @@ +{ + "RawHeader": "random git message (2020-4-1)", + "Type": "misc", + "Scope": "" +} \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Mixedcase.golden b/pkg/convention/testdata/TestNewCommit/Mixedcase.golden index dbaabcc..bd7de8b 100644 --- a/pkg/convention/testdata/TestNewCommit/Mixedcase.golden +++ b/pkg/convention/testdata/TestNewCommit/Mixedcase.golden @@ -1,5 +1,5 @@ { - "RawHeader": "Docs: correct spelling of CHANGELOG", + "RawHeader": "Docs: correct spelling of CHANGELOG (1-1-1)", "Type": "docs", "Scope": "" } \ No newline at end of file diff --git a/pkg/convention/testdata/TestNewCommit/Uppercase.golden b/pkg/convention/testdata/TestNewCommit/Uppercase.golden index aa7e76e..544dc10 100644 --- a/pkg/convention/testdata/TestNewCommit/Uppercase.golden +++ b/pkg/convention/testdata/TestNewCommit/Uppercase.golden @@ -1,5 +1,5 @@ { - "RawHeader": "REFACTOR!: drop support for Node 6", + "RawHeader": "REFACTOR!: drop support for Node 6 (1-1-1)", "Type": "refactor", "Scope": "" } \ No newline at end of file diff --git a/pkg/git/author.go b/pkg/git/author.go new file mode 100644 index 0000000..691a71c --- /dev/null +++ b/pkg/git/author.go @@ -0,0 +1,9 @@ +package git + +import "time" + +type Author struct { + Name string + Email string + When time.Time +} diff --git a/pkg/git/commit.go b/pkg/git/commit.go index 79ae08f..6f808ff 100644 --- a/pkg/git/commit.go +++ b/pkg/git/commit.go @@ -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, + }, } }