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:
tsuyoshi wada 2018-03-02 09:48:02 +09:00 committed by GitHub
commit d3f14a305d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 384 additions and 201 deletions

View file

@ -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
View file

@ -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

View file

@ -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"

View file

@ -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)
} }

View 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}}`
}

View file

@ -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,

View file

@ -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
} }

View file

@ -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())

View 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}}`
}

View 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)
}

View file

@ -132,7 +132,7 @@ func main() {
fs, fs,
), ),
NewConfigBuilder(), NewConfigBuilder(),
NewTemplateBuilder(), templateBuilderFactory,
) )
os.Exit(initializer.Run()) os.Exit(initializer.Run())

View file

@ -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}}`
} }

View file

@ -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,
} }

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

View file

@ -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