diff --git a/chglog.go b/chglog.go index 1a084c8a..f4d93e9d 100644 --- a/chglog.go +++ b/chglog.go @@ -54,9 +54,10 @@ type Info struct { // RenderData is the data passed to the template type RenderData struct { - Info *Info - Unreleased *Unreleased - Versions []*Version + Info *Info + Unreleased *Unreleased + Versions []*Version + UnreleasedHash *Hash } // Config for generating CHANGELOG @@ -162,7 +163,7 @@ func (gen *Generator) Generate(w io.Writer, query string) error { return err } - if len(versions) == 0 { + if len(versions) == 0 && query != "" { return fmt.Errorf("commits corresponding to \"%s\" was not found", query) } @@ -284,7 +285,8 @@ func (gen *Generator) getTags(query string) ([]*Tag, string, error) { }, tags...) } - if len(tags) == 0 { + // Error only when you explicitly set a query + if len(tags) == 0 && query != "" { return nil, "", errors.New("git-tag does not exist") } @@ -353,9 +355,18 @@ func (gen *Generator) render(w io.Writer, unreleased *Unreleased, versions []*Ve t := template.Must(template.New(fname).Funcs(sprig.TxtFuncMap()).Funcs(fmap).ParseFiles(gen.config.Template)) + unreleasedHash := &Hash{} + + if unreleased.CommitGroups != nil && len(unreleased.CommitGroups) > 0 { + unreleasedHash = unreleased.CommitGroups[0].Commits[0].Hash + } else if unreleased.Commits != nil && len(unreleased.Commits) > 0 { + unreleasedHash = unreleased.Commits[0].Hash + } + return t.Execute(w, &RenderData{ - Info: gen.config.Info, - Unreleased: unreleased, - Versions: versions, + Info: gen.config.Info, + Unreleased: unreleased, + Versions: versions, + UnreleasedHash: unreleasedHash, }) } diff --git a/chglog_test.go b/chglog_test.go index a00359bb..da61ddfe 100644 --- a/chglog_test.go +++ b/chglog_test.go @@ -70,7 +70,7 @@ func cleanup() { func TestGeneratorNotFoundTags(t *testing.T) { assert := assert.New(t) - testName := "not_found" + testName := "no_tags" setup(testName, func(commit commitFunc, _ tagFunc, _ gitcmd.Client) { commit("2018-01-01 00:00:00", "feat(*): New feature", "") @@ -91,9 +91,8 @@ func TestGeneratorNotFoundTags(t *testing.T) { err := gen.Generate(buf, "") expected := strings.TrimSpace(buf.String()) - assert.Error(err) - assert.Contains(err.Error(), "git-tag does not exist") - assert.Equal("", expected) + assert.Nil(err) + assert.Contains(expected, "\n## [Unreleased]") } func TestGeneratorNotFoundCommits(t *testing.T) { @@ -629,3 +628,107 @@ func TestGeneratorWithSprig(t *testing.T) { [2.0.0]: https://github.com/git-chglog/git-chglog/compare/1.0.0...2.0.0`, expected) } + +var ( + styleGitHub = "github" + fmtTypeScopeSubject = "(): " + tplKeepAChangelog = "keep-a-changelog" +) + +func TestNewRepoUnreleasedCommitsButNoTags(t *testing.T) { + asrt := assert.New(t) + testName := "commits_and_no_tags" + + setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) { + commit("2023-06-25 00:00:00", "feat: Second Feature", "") + commit("2023-06-24 00:00:00", "feat: First Feature", "") + }) + + gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true), + &Config{ + Bin: "git", + WorkingDir: filepath.Join(testRepoRoot, testName), + Template: filepath.Join(cwd, "testdata", testName+".md"), + Info: &Info{ + Title: "CHANGELOG Example", + RepositoryURL: "https://github.com/git-chglog/git-chglog", + }, + Options: &Options{ + CommitGroupBy: "Type", + CommitGroupTitleMaps: map[string]string{ + "feat": "Features", + }, + HeaderPattern: "^(\\w*)\\:\\s(.*)$", + HeaderPatternMaps: []string{ + "Type", + "Subject", + }}, + }) + + buf := &bytes.Buffer{} + err := gen.Generate(buf, "") + actual := strings.TrimSpace(buf.String()) + + asrt.NoError(err) + asrt.Contains(actual, ` +## [Unreleased] + +### Features +- First Feature +- Second Feature + + +[Unreleased]: https://github.com/git-chglog/git-chglog/compare/`) + +} + +func TestNewRepoUnreleasedCommitsWithNextTag(t *testing.T) { + asrt := assert.New(t) + testName := "commits_and_next_tag" + + setup(testName, func(commit commitFunc, tag tagFunc, _ gitcmd.Client) { + commit("2023-06-25 00:00:00", "feat: Second Feature", "") + commit("2023-06-24 00:00:00", "feat: First Feature", "") + }) + + gen := NewGenerator(NewLogger(os.Stdout, os.Stderr, false, true), + &Config{ + Bin: "git", + WorkingDir: filepath.Join(testRepoRoot, testName), + Template: filepath.Join(cwd, "testdata", testName+".md"), + Info: &Info{ + Title: "CHANGELOG Example", + RepositoryURL: "https://github.com/git-chglog/git-chglog", + }, + Options: &Options{ + NextTag: "0.1.0", + CommitGroupBy: "Type", + CommitGroupTitleMaps: map[string]string{ + "feat": "Features", + }, + HeaderPattern: "^(\\w*)\\:\\s(.*)$", + HeaderPatternMaps: []string{ + "Type", + "Subject", + }}, + }) + + buf := &bytes.Buffer{} + err := gen.Generate(buf, "") + actual := strings.TrimSpace(buf.String()) + + asrt.NoError(err) + asrt.Equal(` +## [Unreleased] + + + +## 0.1.0 - 2023-06-24 +### Features +- First Feature +- Second Feature + + +[Unreleased]: https://github.com/git-chglog/git-chglog/compare/0.1.0...HEAD`, actual) + +} diff --git a/cmd/git-chglog/kac_template_builder.go b/cmd/git-chglog/kac_template_builder.go index e0956d2f..e7d50c97 100644 --- a/cmd/git-chglog/kac_template_builder.go +++ b/cmd/git-chglog/kac_template_builder.go @@ -57,7 +57,7 @@ func (t *kacTemplateBuilderImpl) unreleased(style, format string) string { title = fmt.Sprintf("[%s]", title) } - return fmt.Sprintf(`{{ if .Versions -}} + return fmt.Sprintf(`{{ if .Unreleased -}} %s## %s {{ if .Unreleased.CommitGroups -}} @@ -156,24 +156,30 @@ func (*kacTemplateBuilderImpl) footer(style string) string { case styleGitHub, styleGitLab: return ` -{{- if .Versions }} +{{ if .UnreleasedHash.Short -}} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ .UnreleasedHash.Short }}...HEAD +{{ end -}} +{{ if .Versions -}} [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ end -}} {{ range .Versions -}} {{ if .Tag.Previous -}} [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} {{ end -}} -{{ end -}} {{ end -}}` case styleBitbucket: return ` -{{- if .Versions }} -[Unreleased]: {{ .Info.RepositoryURL }}/compare/HEAD..{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }} +{{ if .UnreleasedHash.Short -}} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ .UnreleasedHash.Short }}...HEAD +{{ end -}} +{{ if .Versions -}} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ end -}} {{ range .Versions -}} {{ if .Tag.Previous -}} [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Name }}..{{ .Tag.Previous.Name }} {{ end -}} -{{ end -}} {{ end -}}` default: return "" diff --git a/cmd/git-chglog/kac_template_builder_test.go b/cmd/git-chglog/kac_template_builder_test.go index 70170aac..666de0d9 100644 --- a/cmd/git-chglog/kac_template_builder_test.go +++ b/cmd/git-chglog/kac_template_builder_test.go @@ -19,7 +19,7 @@ func TestKACTemplateBuilderDefault(t *testing.T) { }) assert.Nil(err) - assert.Equal(`{{ if .Versions -}} + assert.Equal(`{{ if .Unreleased -}} ## [Unreleased] @@ -67,13 +67,16 @@ func TestKACTemplateBuilderDefault(t *testing.T) { {{ end -}} {{ end -}} +{{- if .UnreleasedHash.Short }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ .UnreleasedHash.Short }}...HEAD +{{ end -}} {{- if .Versions }} [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ end -}} {{ range .Versions -}} {{ if .Tag.Previous -}} [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} {{ end -}} -{{ end -}} {{ end -}}`, out) } @@ -90,7 +93,7 @@ func TestKACTemplateBuilderNone(t *testing.T) { }) assert.Nil(err) - assert.Equal(`{{ if .Versions -}} + assert.Equal(`{{ if .Unreleased -}} ## Unreleased {{ if .Unreleased.CommitGroups -}} @@ -150,7 +153,7 @@ func TestKACTemplateBuilderSubject(t *testing.T) { }) assert.Nil(err) - assert.Equal(`{{ if .Versions -}} + assert.Equal(`{{ if .Unreleased -}} ## Unreleased {{ if .Unreleased.CommitGroups -}} diff --git a/testdata/commits_and_next_tag.md b/testdata/commits_and_next_tag.md new file mode 100644 index 00000000..ea9b5fa7 --- /dev/null +++ b/testdata/commits_and_next_tag.md @@ -0,0 +1,52 @@ +{{ if .Unreleased -}} + +## [Unreleased] + +{{ if .Unreleased.CommitGroups -}} +{{ range .Unreleased.CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{ range .Versions }} + +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} +{{ range .CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} + +{{- if .RevertCommits -}} +### Reverts +{{ range .RevertCommits -}} +- {{ .Revert.Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +### {{ .Title }} +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{- if .UnreleasedHash.Short }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ .UnreleasedHash.Short }}...HEAD +{{ end -}} +{{- if .Versions }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ end -}} +{{ range .Versions -}} +{{ if .Tag.Previous -}} +[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/testdata/commits_and_no_tags.md b/testdata/commits_and_no_tags.md new file mode 100644 index 00000000..ea9b5fa7 --- /dev/null +++ b/testdata/commits_and_no_tags.md @@ -0,0 +1,52 @@ +{{ if .Unreleased -}} + +## [Unreleased] + +{{ if .Unreleased.CommitGroups -}} +{{ range .Unreleased.CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{ range .Versions }} + +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} +{{ range .CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} + +{{- if .RevertCommits -}} +### Reverts +{{ range .RevertCommits -}} +- {{ .Revert.Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +### {{ .Title }} +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{- if .UnreleasedHash.Short }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ .UnreleasedHash.Short }}...HEAD +{{ end -}} +{{- if .Versions }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ end -}} +{{ range .Versions -}} +{{ if .Tag.Previous -}} +[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/testdata/no_tags.md b/testdata/no_tags.md new file mode 100644 index 00000000..f809cfef --- /dev/null +++ b/testdata/no_tags.md @@ -0,0 +1,54 @@ +{{ if .Unreleased -}} + +## [Unreleased] + +{{ if .Unreleased.CommitGroups -}} +{{ range .Unreleased.CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{ range .Versions }} + +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} +{{ range .CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} + +{{- if .RevertCommits -}} +### Reverts +{{ range .RevertCommits -}} +- {{ .Revert.Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +### {{ .Title }} +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{- if .Unreleased -}} +{{- $latest := index .Unreleased.Commits 0 -}} +{{- if .Unreleased.CommitGroups -}} +{{- $group = index .Unreleased.CommitGroups 0 -}} +{{- $latest = index $group.Commits 0 -}} +{{- end }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest.Hash }}...HEAD +{{ end -}} +{{ range .Versions -}} +{{ if .Tag.Previous -}} +[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} +{{ end -}} +{{ end -}} \ No newline at end of file