mirror of
https://github.com/git-chglog/git-chglog.git
synced 2026-01-23 02:15:12 +00:00
Merge pull request #11 from git-chglog/develop
New template and pass all the test cases with windows! and usability update.
This commit is contained in:
commit
d3f14a305d
18 changed files with 384 additions and 201 deletions
17
.travis.yml
17
.travis.yml
|
|
@ -6,17 +6,20 @@ go:
|
||||||
- 1.9
|
- 1.9
|
||||||
before_install:
|
before_install:
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
- go get github.com/mitchellh/gox
|
|
||||||
- go get github.com/tcnksm/ghr
|
|
||||||
before_script:
|
before_script:
|
||||||
- export TZ=Asia/Tokyo
|
- export TZ=Asia/Tokyo
|
||||||
- sudo timedatectl set-timezone Asia/Tokyo
|
- sudo timedatectl set-timezone Asia/Tokyo
|
||||||
- timedatectl
|
- timedatectl
|
||||||
script:
|
script:
|
||||||
- make test
|
- make test
|
||||||
- goveralls -service=travis-ci
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
after_success:
|
after_success:
|
||||||
- ./scripts/release.sh
|
- goveralls -service=travis-ci
|
||||||
|
before_deploy:
|
||||||
|
- go get github.com/mitchellh/gox
|
||||||
|
- go get github.com/tcnksm/ghr
|
||||||
|
deploy:
|
||||||
|
provider: script
|
||||||
|
script: ./scripts/release.sh
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
branch: master
|
||||||
|
|
|
||||||
6
Gopkg.lock
generated
6
Gopkg.lock
generated
|
|
@ -74,8 +74,8 @@
|
||||||
"core",
|
"core",
|
||||||
"terminal"
|
"terminal"
|
||||||
]
|
]
|
||||||
revision = "0aa8b6a162b391fe2d95648b7677d1d6ac2090a6"
|
revision = "9f89d9dd66613216993dc300f9f3dbae9c3c9bda"
|
||||||
version = "v1.4.1"
|
version = "v1.4.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "gopkg.in/kyokomi/emoji.v1"
|
name = "gopkg.in/kyokomi/emoji.v1"
|
||||||
|
|
@ -92,6 +92,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "0be1d1c2f1a9b1c1f1d63ad065141425b62687efb378f6657b088ddf993c3882"
|
inputs-digest = "da532fb70b3049dffe6ae9f73b3f0a742452639096a325ac5d2400be6ad0559e"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "gopkg.in/AlecAivazis/survey.v1"
|
name = "gopkg.in/AlecAivazis/survey.v1"
|
||||||
version = "1.4.1"
|
version = "1.4.2"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "gopkg.in/kyokomi/emoji.v1"
|
name = "gopkg.in/kyokomi/emoji.v1"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -18,7 +19,7 @@ func TestConfigNormalize(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err := config.Normalize(&CLIContext{
|
err := config.Normalize(&CLIContext{
|
||||||
ConfigPath: "/test/config.yml",
|
ConfigPath: filepath.FromSlash("/test/config.yml"),
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
|
|
@ -27,14 +28,16 @@ func TestConfigNormalize(t *testing.T) {
|
||||||
assert.Equal("/test/CHANGELOG.tpl.md", filepath.ToSlash(config.Template))
|
assert.Equal("/test/CHANGELOG.tpl.md", filepath.ToSlash(config.Template))
|
||||||
|
|
||||||
// abs template
|
// abs template
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
|
||||||
config = &Config{
|
config = &Config{
|
||||||
Template: "/CHANGELOG.tpl.md",
|
Template: filepath.Join(cwd, "CHANGELOG.tpl.md"),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Normalize(&CLIContext{
|
err = config.Normalize(&CLIContext{
|
||||||
ConfigPath: "/test/config.yml",
|
ConfigPath: filepath.Join(cwd, "test", "config.yml"),
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
assert.Equal("/CHANGELOG.tpl.md", filepath.ToSlash(config.Template))
|
assert.Equal(filepath.Join(cwd, "CHANGELOG.tpl.md"), config.Template)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
136
cmd/git-chglog/custom_template_builder.go
Normal file
136
cmd/git-chglog/custom_template_builder.go
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type customTemplateBuilderImpl struct{}
|
||||||
|
|
||||||
|
// NewCustomTemplateBuilder ...
|
||||||
|
func NewCustomTemplateBuilder() TemplateBuilder {
|
||||||
|
return &customTemplateBuilderImpl{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build ...
|
||||||
|
func (t *customTemplateBuilderImpl) Build(ans *Answer) (string, error) {
|
||||||
|
// versions
|
||||||
|
tpl := "{{range .Versions}}\n"
|
||||||
|
|
||||||
|
// version header
|
||||||
|
tpl += t.versionHeader(ans.Style, ans.Template)
|
||||||
|
|
||||||
|
// commits
|
||||||
|
tpl += t.commits(ans.Template, ans.CommitMessageFormat)
|
||||||
|
|
||||||
|
// revert
|
||||||
|
if ans.IncludeReverts {
|
||||||
|
tpl += t.reverts()
|
||||||
|
}
|
||||||
|
|
||||||
|
// merges
|
||||||
|
if ans.IncludeMerges {
|
||||||
|
tpl += t.merges(ans.Style)
|
||||||
|
}
|
||||||
|
|
||||||
|
// notes
|
||||||
|
tpl += t.notes()
|
||||||
|
|
||||||
|
// versions end
|
||||||
|
tpl += "\n{{end}}"
|
||||||
|
|
||||||
|
return tpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*customTemplateBuilderImpl) versionHeader(style, template string) string {
|
||||||
|
var (
|
||||||
|
tpl string
|
||||||
|
tagName = "{{.Tag.Name}}"
|
||||||
|
date = "{{datetime \"2006-01-02\" .Tag.Date}}"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parts
|
||||||
|
switch style {
|
||||||
|
case styleGitHub:
|
||||||
|
tpl = "<a name=\"{{.Tag.Name}}\"></a>\n"
|
||||||
|
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}){{else}}{{.Tag.Name}}{{end}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// format
|
||||||
|
switch template {
|
||||||
|
case tplStandard:
|
||||||
|
tpl = fmt.Sprintf("%s## %s (%s)\n",
|
||||||
|
tpl,
|
||||||
|
tagName,
|
||||||
|
date,
|
||||||
|
)
|
||||||
|
case tplCool:
|
||||||
|
tpl = fmt.Sprintf("%s## %s\n\n> %s\n",
|
||||||
|
tpl,
|
||||||
|
tagName,
|
||||||
|
date,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*customTemplateBuilderImpl) commits(template, format string) string {
|
||||||
|
var (
|
||||||
|
header string
|
||||||
|
body string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch format {
|
||||||
|
case fmtSubject.Display:
|
||||||
|
body = `{{range .Commits}}
|
||||||
|
* {{.Header}}{{end}}
|
||||||
|
`
|
||||||
|
|
||||||
|
default:
|
||||||
|
if format == fmtTypeScopeSubject.Display {
|
||||||
|
header = "{{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}}"
|
||||||
|
} else {
|
||||||
|
header = "{{.Subject}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
body = fmt.Sprintf(`### {{.Title}}
|
||||||
|
{{range .Commits}}
|
||||||
|
* %s{{end}}
|
||||||
|
`, header)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`{{range .CommitGroups}}
|
||||||
|
%s{{end}}`, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*customTemplateBuilderImpl) reverts() string {
|
||||||
|
return `{{if .RevertCommits}}
|
||||||
|
### Reverts
|
||||||
|
{{range .RevertCommits}}
|
||||||
|
* {{.Revert.Header}}{{end}}
|
||||||
|
{{end}}`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *customTemplateBuilderImpl) merges(style string) string {
|
||||||
|
var title string
|
||||||
|
|
||||||
|
switch style {
|
||||||
|
case styleGitHub:
|
||||||
|
title = "Pull Requests"
|
||||||
|
default:
|
||||||
|
title = "Merges"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`{{if .MergeCommits}}
|
||||||
|
### %s
|
||||||
|
{{range .MergeCommits}}
|
||||||
|
* {{.Header}}{{end}}
|
||||||
|
{{end}}`, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*customTemplateBuilderImpl) notes() string {
|
||||||
|
return `{{range .NoteGroups}}
|
||||||
|
### {{.Title}}
|
||||||
|
{{range .Notes}}
|
||||||
|
{{.Body}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}`
|
||||||
|
}
|
||||||
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTemplateBuilderDefault(t *testing.T) {
|
func TestCustomTemplateBuilderDefault(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleGitHub,
|
Style: styleGitHub,
|
||||||
|
|
@ -25,7 +25,7 @@ func TestTemplateBuilderDefault(t *testing.T) {
|
||||||
{{range .CommitGroups}}
|
{{range .CommitGroups}}
|
||||||
### {{.Title}}
|
### {{.Title}}
|
||||||
{{range .Commits}}
|
{{range .Commits}}
|
||||||
* {{if ne .Scope ""}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
* {{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
||||||
{{end}}{{if .RevertCommits}}
|
{{end}}{{if .RevertCommits}}
|
||||||
### Reverts
|
### Reverts
|
||||||
{{range .RevertCommits}}
|
{{range .RevertCommits}}
|
||||||
|
|
@ -43,9 +43,9 @@ func TestTemplateBuilderDefault(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderNone(t *testing.T) {
|
func TestCustomTemplateBuilderNone(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -61,7 +61,7 @@ func TestTemplateBuilderNone(t *testing.T) {
|
||||||
{{range .CommitGroups}}
|
{{range .CommitGroups}}
|
||||||
### {{.Title}}
|
### {{.Title}}
|
||||||
{{range .Commits}}
|
{{range .Commits}}
|
||||||
* {{if ne .Scope ""}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
* {{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
||||||
{{end}}{{if .RevertCommits}}
|
{{end}}{{if .RevertCommits}}
|
||||||
### Reverts
|
### Reverts
|
||||||
{{range .RevertCommits}}
|
{{range .RevertCommits}}
|
||||||
|
|
@ -79,9 +79,9 @@ func TestTemplateBuilderNone(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderCool(t *testing.T) {
|
func TestCustomTemplateBuilderCool(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -99,7 +99,7 @@ func TestTemplateBuilderCool(t *testing.T) {
|
||||||
{{range .CommitGroups}}
|
{{range .CommitGroups}}
|
||||||
### {{.Title}}
|
### {{.Title}}
|
||||||
{{range .Commits}}
|
{{range .Commits}}
|
||||||
* {{if ne .Scope ""}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
* {{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}
|
||||||
{{end}}{{if .RevertCommits}}
|
{{end}}{{if .RevertCommits}}
|
||||||
### Reverts
|
### Reverts
|
||||||
{{range .RevertCommits}}
|
{{range .RevertCommits}}
|
||||||
|
|
@ -117,9 +117,9 @@ func TestTemplateBuilderCool(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderSubjectOnly(t *testing.T) {
|
func TestCustomTemplateBuilderSubjectOnly(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -152,9 +152,9 @@ func TestTemplateBuilderSubjectOnly(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderSubject(t *testing.T) {
|
func TestCustomTemplateBuilderSubject(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -188,9 +188,9 @@ func TestTemplateBuilderSubject(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderIgnoreReverts(t *testing.T) {
|
func TestCustomTemplateBuilderIgnoreReverts(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -220,9 +220,9 @@ func TestTemplateBuilderIgnoreReverts(t *testing.T) {
|
||||||
{{end}}`, out)
|
{{end}}`, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateBuilderIgnoreMerges(t *testing.T) {
|
func TestCustomTemplateBuilderIgnoreMerges(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
builder := NewTemplateBuilder()
|
builder := NewCustomTemplateBuilder()
|
||||||
|
|
||||||
out, err := builder.Build(&Answer{
|
out, err := builder.Build(&Answer{
|
||||||
Style: styleNone,
|
Style: styleNone,
|
||||||
|
|
@ -10,13 +10,13 @@ import (
|
||||||
|
|
||||||
// Initializer ...
|
// Initializer ...
|
||||||
type Initializer struct {
|
type Initializer struct {
|
||||||
ctx *InitContext
|
ctx *InitContext
|
||||||
client gitcmd.Client
|
client gitcmd.Client
|
||||||
fs FileSystem
|
fs FileSystem
|
||||||
logger *Logger
|
logger *Logger
|
||||||
questioner Questioner
|
questioner Questioner
|
||||||
configBuilder ConfigBuilder
|
configBuilder ConfigBuilder
|
||||||
templateBuilder TemplateBuilder
|
templateBuilderFactory TemplateBuilderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInitializer ...
|
// NewInitializer ...
|
||||||
|
|
@ -25,15 +25,14 @@ func NewInitializer(
|
||||||
fs FileSystem,
|
fs FileSystem,
|
||||||
questioner Questioner,
|
questioner Questioner,
|
||||||
configBuilder ConfigBuilder,
|
configBuilder ConfigBuilder,
|
||||||
templateBuilder TemplateBuilder,
|
tplBuilderFactory TemplateBuilderFactory) *Initializer {
|
||||||
) *Initializer {
|
|
||||||
return &Initializer{
|
return &Initializer{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
fs: fs,
|
fs: fs,
|
||||||
logger: NewLogger(ctx.Stdout, ctx.Stderr, false, false),
|
logger: NewLogger(ctx.Stdout, ctx.Stderr, false, false),
|
||||||
questioner: questioner,
|
questioner: questioner,
|
||||||
configBuilder: configBuilder,
|
configBuilder: configBuilder,
|
||||||
templateBuilder: templateBuilder,
|
templateBuilderFactory: tplBuilderFactory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +85,8 @@ func (init *Initializer) generateConfig(ans *Answer) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (init *Initializer) generateTemplate(ans *Answer) error {
|
func (init *Initializer) generateTemplate(ans *Answer) error {
|
||||||
s, err := init.templateBuilder.Build(ans)
|
templateBuilder := init.templateBuilderFactory(ans.Template)
|
||||||
|
s, err := templateBuilder.Build(ans)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -16,13 +17,13 @@ func TestInitializer(t *testing.T) {
|
||||||
|
|
||||||
mockFs := &mockFileSystem{
|
mockFs := &mockFileSystem{
|
||||||
ReturnMkdirP: func(path string) error {
|
ReturnMkdirP: func(path string) error {
|
||||||
if path == "/test/config" {
|
if path == filepath.FromSlash("/test/config") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("")
|
return errors.New("")
|
||||||
},
|
},
|
||||||
ReturnWriteFile: func(path string, content []byte) error {
|
ReturnWriteFile: func(path string, content []byte) error {
|
||||||
if path == "/test/config/config.yml" || path == "/test/config/CHANGELOG.tpl.md" {
|
if path == filepath.FromSlash("/test/config/config.yml") || path == filepath.FromSlash("/test/config/CHANGELOG.tpl.md") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("")
|
return errors.New("")
|
||||||
|
|
@ -64,7 +65,9 @@ func TestInitializer(t *testing.T) {
|
||||||
mockFs,
|
mockFs,
|
||||||
questioner,
|
questioner,
|
||||||
configBuilder,
|
configBuilder,
|
||||||
tplBuilder,
|
func(t string) TemplateBuilder {
|
||||||
|
return tplBuilder
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.Equal(ExitCodeOK, init.Run())
|
assert.Equal(ExitCodeOK, init.Run())
|
||||||
|
|
|
||||||
118
cmd/git-chglog/kac_template_builder.go
Normal file
118
cmd/git-chglog/kac_template_builder.go
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type kacTemplateBuilderImpl struct{}
|
||||||
|
|
||||||
|
// NewKACTemplateBuilder ...
|
||||||
|
func NewKACTemplateBuilder() TemplateBuilder {
|
||||||
|
return &kacTemplateBuilderImpl{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build ...
|
||||||
|
func (t *kacTemplateBuilderImpl) Build(ans *Answer) (string, error) {
|
||||||
|
// versions
|
||||||
|
tpl := "## {{if .Versions}}[Unreleased]{{end}}\n{{range .Versions}}\n"
|
||||||
|
tpl += t.versionHeader(ans.Style)
|
||||||
|
|
||||||
|
// commits
|
||||||
|
tpl += t.commits(ans.CommitMessageFormat)
|
||||||
|
|
||||||
|
// revert
|
||||||
|
if ans.IncludeReverts {
|
||||||
|
tpl += t.reverts()
|
||||||
|
}
|
||||||
|
|
||||||
|
// merges
|
||||||
|
if ans.IncludeMerges {
|
||||||
|
tpl += t.merges(ans.Style)
|
||||||
|
}
|
||||||
|
|
||||||
|
// notes
|
||||||
|
tpl += t.notes()
|
||||||
|
|
||||||
|
// versions end
|
||||||
|
tpl += "{{end}}"
|
||||||
|
|
||||||
|
// footer (links)
|
||||||
|
tpl += t.footer(ans.Style)
|
||||||
|
|
||||||
|
return tpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *kacTemplateBuilderImpl) versionHeader(style string) string {
|
||||||
|
var (
|
||||||
|
tagName = "{{.Tag.Name}}"
|
||||||
|
date = "{{datetime \"2006-01-02\" .Tag.Date}}"
|
||||||
|
)
|
||||||
|
|
||||||
|
switch style {
|
||||||
|
case styleGitHub:
|
||||||
|
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]{{else}}{{.Tag.Name}}{{end}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("## %s - %s", tagName, date)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *kacTemplateBuilderImpl) commits(format string) string {
|
||||||
|
var (
|
||||||
|
body string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch format {
|
||||||
|
case fmtSubject.Display:
|
||||||
|
body = `{{range .Commits}}
|
||||||
|
- {{.Header}}{{end}}`
|
||||||
|
|
||||||
|
default:
|
||||||
|
body = `### {{.Title}}{{range .Commits}}
|
||||||
|
- {{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}}{{end}}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`{{range .CommitGroups}}
|
||||||
|
%s
|
||||||
|
{{end}}`, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *kacTemplateBuilderImpl) reverts() string {
|
||||||
|
return `{{if .RevertCommits}}
|
||||||
|
### Reverts{{range .RevertCommits}}
|
||||||
|
- {{.Revert.Header}}{{end}}
|
||||||
|
{{end}}`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *kacTemplateBuilderImpl) merges(style string) string {
|
||||||
|
var title string
|
||||||
|
|
||||||
|
switch style {
|
||||||
|
case styleGitHub:
|
||||||
|
title = "Pull Requests"
|
||||||
|
default:
|
||||||
|
title = "Merges"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`{{if .MergeCommits}}
|
||||||
|
### %s{{range .MergeCommits}}
|
||||||
|
- {{.Header}}{{end}}
|
||||||
|
{{end}}`, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*kacTemplateBuilderImpl) notes() string {
|
||||||
|
return `{{range .NoteGroups}}
|
||||||
|
### {{.Title}}
|
||||||
|
{{range .Notes}}
|
||||||
|
{{.Body}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*kacTemplateBuilderImpl) footer(style string) string {
|
||||||
|
if style != styleGitHub {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return `{{if .Versions}}
|
||||||
|
[Unreleased]: {{.Info.RepositoryURL}}/compare/{{$latest := index .Versions 0}}{{$latest.Tag.Name}}...HEAD{{range .Versions}}{{if .Tag.Previous}}
|
||||||
|
[{{.Tag.Name}}]: {{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}{{end}}{{end}}
|
||||||
|
{{end}}`
|
||||||
|
}
|
||||||
42
cmd/git-chglog/kac_template_builder_test.go
Normal file
42
cmd/git-chglog/kac_template_builder_test.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKACTemplateBuilderDefault(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
builder := NewKACTemplateBuilder()
|
||||||
|
|
||||||
|
out, err := builder.Build(&Answer{
|
||||||
|
Style: styleGitHub,
|
||||||
|
CommitMessageFormat: fmtTypeScopeSubject.Display,
|
||||||
|
Template: tplKeepAChangelog,
|
||||||
|
IncludeMerges: true,
|
||||||
|
IncludeReverts: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Nil(err)
|
||||||
|
assert.Equal(`## {{if .Versions}}[Unreleased]{{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 .MergeCommits}}
|
||||||
|
### Pull Requests{{range .MergeCommits}}
|
||||||
|
- {{.Header}}{{end}}
|
||||||
|
{{end}}{{range .NoteGroups}}
|
||||||
|
### {{.Title}}
|
||||||
|
{{range .Notes}}
|
||||||
|
{{.Body}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}{{end}}{{if .Versions}}
|
||||||
|
[Unreleased]: {{.Info.RepositoryURL}}/compare/{{$latest := index .Versions 0}}{{$latest.Tag.Name}}...HEAD{{range .Versions}}{{if .Tag.Previous}}
|
||||||
|
[{{.Tag.Name}}]: {{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}{{end}}{{end}}
|
||||||
|
{{end}}`, out)
|
||||||
|
}
|
||||||
|
|
@ -132,7 +132,7 @@ func main() {
|
||||||
fs,
|
fs,
|
||||||
),
|
),
|
||||||
NewConfigBuilder(),
|
NewConfigBuilder(),
|
||||||
NewTemplateBuilder(),
|
templateBuilderFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
os.Exit(initializer.Run())
|
os.Exit(initializer.Run())
|
||||||
|
|
|
||||||
|
|
@ -1,143 +1,18 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// TemplateBuilder ...
|
// TemplateBuilder ...
|
||||||
type TemplateBuilder interface {
|
type TemplateBuilder interface {
|
||||||
Builder
|
Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
type templateBuilderImpl struct{}
|
// TemplateBuilderFactory ...
|
||||||
|
type TemplateBuilderFactory = func(string) TemplateBuilder
|
||||||
|
|
||||||
// NewTemplateBuilder ...
|
func templateBuilderFactory(template string) TemplateBuilder {
|
||||||
func NewTemplateBuilder() TemplateBuilder {
|
|
||||||
return &templateBuilderImpl{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build ...
|
|
||||||
func (t *templateBuilderImpl) Build(ans *Answer) (string, error) {
|
|
||||||
// versions
|
|
||||||
tpl := "{{range .Versions}}\n"
|
|
||||||
|
|
||||||
// version header
|
|
||||||
tpl += t.versionHeader(ans.Style, ans.Template)
|
|
||||||
|
|
||||||
// commits
|
|
||||||
tpl += t.commits(ans.Template, ans.CommitMessageFormat)
|
|
||||||
|
|
||||||
// revert
|
|
||||||
if ans.IncludeReverts {
|
|
||||||
tpl += t.reverts()
|
|
||||||
}
|
|
||||||
|
|
||||||
// merges
|
|
||||||
if ans.IncludeMerges {
|
|
||||||
tpl += t.merges(ans.Style)
|
|
||||||
}
|
|
||||||
|
|
||||||
// notes
|
|
||||||
tpl += t.notes()
|
|
||||||
|
|
||||||
// versions end
|
|
||||||
tpl += "\n{{end}}"
|
|
||||||
|
|
||||||
return tpl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*templateBuilderImpl) versionHeader(style, template string) string {
|
|
||||||
var (
|
|
||||||
tpl string
|
|
||||||
tagName string
|
|
||||||
date = "{{datetime \"2006-01-02\" .Tag.Date}}"
|
|
||||||
)
|
|
||||||
|
|
||||||
// parts
|
|
||||||
switch style {
|
|
||||||
case styleGitHub:
|
|
||||||
tpl = "<a name=\"{{.Tag.Name}}\"></a>\n"
|
|
||||||
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}){{else}}{{.Tag.Name}}{{end}}"
|
|
||||||
default:
|
|
||||||
tagName = "{{.Tag.Name}}"
|
|
||||||
}
|
|
||||||
|
|
||||||
// format
|
|
||||||
switch template {
|
switch template {
|
||||||
case tplStandard:
|
case tplKeepAChangelog:
|
||||||
tpl = fmt.Sprintf("%s## %s (%s)\n",
|
return NewKACTemplateBuilder()
|
||||||
tpl,
|
|
||||||
tagName,
|
|
||||||
date,
|
|
||||||
)
|
|
||||||
case tplCool:
|
|
||||||
tpl = fmt.Sprintf("%s## %s\n\n> %s\n",
|
|
||||||
tpl,
|
|
||||||
tagName,
|
|
||||||
date,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tpl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*templateBuilderImpl) commits(template, format string) string {
|
|
||||||
var (
|
|
||||||
header string
|
|
||||||
body string
|
|
||||||
)
|
|
||||||
|
|
||||||
switch format {
|
|
||||||
case fmtSubject.Display:
|
|
||||||
body = `{{range .Commits}}
|
|
||||||
* {{.Header}}{{end}}
|
|
||||||
`
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if format == fmtTypeScopeSubject.Display {
|
return NewCustomTemplateBuilder()
|
||||||
header = "{{if ne .Scope \"\"}}**{{.Scope}}:** {{end}}{{.Subject}}"
|
|
||||||
} else {
|
|
||||||
header = "{{.Subject}}"
|
|
||||||
}
|
|
||||||
|
|
||||||
body = fmt.Sprintf(`### {{.Title}}
|
|
||||||
{{range .Commits}}
|
|
||||||
* %s{{end}}
|
|
||||||
`, header)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(`{{range .CommitGroups}}
|
|
||||||
%s{{end}}`, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*templateBuilderImpl) reverts() string {
|
|
||||||
return `{{if .RevertCommits}}
|
|
||||||
### Reverts
|
|
||||||
{{range .RevertCommits}}
|
|
||||||
* {{.Revert.Header}}{{end}}
|
|
||||||
{{end}}`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *templateBuilderImpl) merges(style string) string {
|
|
||||||
var title string
|
|
||||||
|
|
||||||
switch style {
|
|
||||||
case styleGitHub:
|
|
||||||
title = "Pull Requests"
|
|
||||||
default:
|
|
||||||
title = "Merges"
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf(`{{if .MergeCommits}}
|
|
||||||
### %s
|
|
||||||
{{range .MergeCommits}}
|
|
||||||
* {{.Header}}{{end}}
|
|
||||||
{{end}}`, title)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*templateBuilderImpl) notes() string {
|
|
||||||
return `{{range .NoteGroups}}
|
|
||||||
### {{.Title}}
|
|
||||||
{{range .Notes}}
|
|
||||||
{{.Body}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}`
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,11 @@ var (
|
||||||
|
|
||||||
// Templates
|
// Templates
|
||||||
var (
|
var (
|
||||||
tplStandard = "standard"
|
tplKeepAChangelog = "keep-a-changelog"
|
||||||
tplCool = "cool"
|
tplStandard = "standard"
|
||||||
templates = []string{
|
tplCool = "cool"
|
||||||
|
templates = []string{
|
||||||
|
tplKeepAChangelog,
|
||||||
tplStandard,
|
tplStandard,
|
||||||
tplCool,
|
tplCool,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||||
|
|
||||||
if [[ "$TRAVIS_BRANCH" == "master" ]] && [[ "$TRAVIS_TAG" != "" ]] && [[ "$TRAVIS_PULL_REQUEST" == "" ]]; then
|
echo "Start release ..."
|
||||||
echo "Start release ..."
|
|
||||||
gox -os="darwin linux windows" -arch="amd64 386" -output="$REPO_ROOT/dist/{{.Dir}}_{{.OS}}_{{.Arch}}" ./cmd/git-chglog
|
gox -os="darwin linux windows" -arch="amd64 386" -output="$REPO_ROOT/dist/{{.Dir}}_{{.OS}}_{{.Arch}}" ./cmd/git-chglog
|
||||||
ghr --username git-chglog --token $GITHUB_TOKEN --replace `grep 'Version =' ./cmd/git-chglog/version.go | sed -E 's/.*"(.+)"$$/\1/'` dist/
|
ghr --username git-chglog --token $GITHUB_TOKEN --replace `grep 'Version =' ./cmd/git-chglog/version.go | sed -E 's/.*"(.+)"$$/\1/'` dist/
|
||||||
echo "Released!"
|
|
||||||
else
|
echo "Released!"
|
||||||
echo "Skip release"
|
|
||||||
fi
|
|
||||||
|
|
|
||||||
4
vendor/gopkg.in/AlecAivazis/survey.v1/multiselect.go
generated
vendored
4
vendor/gopkg.in/AlecAivazis/survey.v1/multiselect.go
generated
vendored
|
|
@ -61,7 +61,7 @@ var MultiSelectQuestionTemplate = `
|
||||||
|
|
||||||
// OnChange is called on every keypress.
|
// OnChange is called on every keypress.
|
||||||
func (m *MultiSelect) OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
func (m *MultiSelect) OnChange(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {
|
||||||
if key == terminal.KeyArrowUp {
|
if key == terminal.KeyArrowUp || key == 'k' {
|
||||||
// if we are at the top of the list
|
// if we are at the top of the list
|
||||||
if m.selectedIndex == 0 {
|
if m.selectedIndex == 0 {
|
||||||
// go to the bottom
|
// go to the bottom
|
||||||
|
|
@ -70,7 +70,7 @@ func (m *MultiSelect) OnChange(line []rune, pos int, key rune) (newLine []rune,
|
||||||
// decrement the selected index
|
// decrement the selected index
|
||||||
m.selectedIndex--
|
m.selectedIndex--
|
||||||
}
|
}
|
||||||
} else if key == terminal.KeyArrowDown {
|
} else if key == terminal.KeyArrowDown || key == 'j' {
|
||||||
// if we are at the bottom of the list
|
// if we are at the bottom of the list
|
||||||
if m.selectedIndex == len(m.Options)-1 {
|
if m.selectedIndex == len(m.Options)-1 {
|
||||||
// start at the top
|
// start at the top
|
||||||
|
|
|
||||||
8
vendor/gopkg.in/AlecAivazis/survey.v1/select.go
generated
vendored
8
vendor/gopkg.in/AlecAivazis/survey.v1/select.go
generated
vendored
|
|
@ -61,8 +61,8 @@ func (s *Select) OnChange(line []rune, pos int, key rune) (newLine []rune, newPo
|
||||||
// if the user pressed the enter key
|
// if the user pressed the enter key
|
||||||
if key == terminal.KeyEnter {
|
if key == terminal.KeyEnter {
|
||||||
return []rune(s.Options[s.selectedIndex]), 0, true
|
return []rune(s.Options[s.selectedIndex]), 0, true
|
||||||
// if the user pressed the up arrow
|
// if the user pressed the up arrow or 'k' to emulate vim
|
||||||
} else if key == terminal.KeyArrowUp {
|
} else if key == terminal.KeyArrowUp || key == 'k' {
|
||||||
s.useDefault = false
|
s.useDefault = false
|
||||||
|
|
||||||
// if we are at the top of the list
|
// if we are at the top of the list
|
||||||
|
|
@ -73,8 +73,8 @@ func (s *Select) OnChange(line []rune, pos int, key rune) (newLine []rune, newPo
|
||||||
// otherwise we are not at the top of the list so decrement the selected index
|
// otherwise we are not at the top of the list so decrement the selected index
|
||||||
s.selectedIndex--
|
s.selectedIndex--
|
||||||
}
|
}
|
||||||
// if the user pressed down and there is room to move
|
// if the user pressed down or 'j' to emulate vim
|
||||||
} else if key == terminal.KeyArrowDown {
|
} else if key == terminal.KeyArrowDown || key == 'j' {
|
||||||
s.useDefault = false
|
s.useDefault = false
|
||||||
// if we are at the bottom of the list
|
// if we are at the bottom of the list
|
||||||
if s.selectedIndex == len(s.Options)-1 {
|
if s.selectedIndex == len(s.Options)-1 {
|
||||||
|
|
|
||||||
0
vendor/gopkg.in/AlecAivazis/survey.v1/terminal/LICENSE.txt
generated
vendored
Normal file
0
vendor/gopkg.in/AlecAivazis/survey.v1/terminal/LICENSE.txt
generated
vendored
Normal file
5
vendor/gopkg.in/AlecAivazis/survey.v1/validate.go
generated
vendored
5
vendor/gopkg.in/AlecAivazis/survey.v1/validate.go
generated
vendored
|
|
@ -8,8 +8,11 @@ import (
|
||||||
|
|
||||||
// Required does not allow an empty value
|
// Required does not allow an empty value
|
||||||
func Required(val interface{}) error {
|
func Required(val interface{}) error {
|
||||||
|
// the reflect value of the result
|
||||||
|
value := reflect.ValueOf(val)
|
||||||
|
|
||||||
// if the value passed in is the zero value of the appropriate type
|
// if the value passed in is the zero value of the appropriate type
|
||||||
if isZero(reflect.ValueOf(val)) {
|
if isZero(value) && value.Kind() != reflect.Bool {
|
||||||
return errors.New("Value is required")
|
return errors.New("Value is required")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue