diff --git a/cmd/git-chglog/config.go b/cmd/git-chglog/config.go
index 83f1a9ed..a81340ee 100644
--- a/cmd/git-chglog/config.go
+++ b/cmd/git-chglog/config.go
@@ -108,6 +108,10 @@ func (config *Config) normalizeStyle() {
switch config.Style {
case "github":
config.normalizeStyleOfGitHub()
+ case "gitlab":
+ config.normalizeStyleOfGitLab()
+ case "bitbucket":
+ config.normalizeStyleOfBitbucket()
}
}
@@ -184,6 +188,61 @@ func (config *Config) normalizeStyleOfGitLab() {
config.Options = opts
}
+// For Bitbucket
+func (config *Config) normalizeStyleOfBitbucket() {
+ opts := config.Options
+
+ if len(opts.Issues.Prefix) == 0 {
+ opts.Issues.Prefix = []string{
+ "#",
+ }
+ }
+
+ if len(opts.Refs.Actions) == 0 {
+ opts.Refs.Actions = []string{
+ "close",
+ "closes",
+ "closed",
+ "closing",
+ "fix",
+ "fixed",
+ "fixes",
+ "fixing",
+ "resolve",
+ "resolves",
+ "resolved",
+ "resolving",
+ "eopen",
+ "reopens",
+ "reopening",
+ "hold",
+ "holds",
+ "holding",
+ "wontfix",
+ "invalidate",
+ "invalidates",
+ "invalidated",
+ "invalidating",
+ "addresses",
+ "re",
+ "references",
+ "ref",
+ "refs",
+ "see",
+ }
+ }
+
+ if opts.Merges.Pattern == "" && len(opts.Merges.PatternMaps) == 0 {
+ opts.Merges.Pattern = "^Merged in (.*) \\(pull request #(\\d+)\\)$"
+ opts.Merges.PatternMaps = []string{
+ "Source",
+ "Ref",
+ }
+ }
+
+ config.Options = opts
+}
+
// Convert ...
func (config *Config) Convert(ctx *CLIContext) *chglog.Config {
info := config.Info
diff --git a/cmd/git-chglog/custom_template_builder.go b/cmd/git-chglog/custom_template_builder.go
index 48487cff..eba8aa11 100644
--- a/cmd/git-chglog/custom_template_builder.go
+++ b/cmd/git-chglog/custom_template_builder.go
@@ -51,6 +51,9 @@ func (*customTemplateBuilderImpl) versionHeader(style, template string) string {
case styleGitHub, styleGitLab:
tpl = "\n"
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}){{else}}{{.Tag.Name}}{{end}}"
+ case styleBitbucket:
+ tpl = "\n"
+ tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Name}}..{{.Tag.Previous.Name}}){{else}}{{.Tag.Name}}{{end}}"
}
// format
@@ -113,7 +116,7 @@ func (t *customTemplateBuilderImpl) merges(style string) string {
var title string
switch style {
- case styleGitHub:
+ case styleGitHub, styleBitbucket:
title = "Pull Requests"
case styleGitLab:
title = "Merge Requests"
diff --git a/cmd/git-chglog/kac_template_builder.go b/cmd/git-chglog/kac_template_builder.go
index d929063a..5c0e816e 100644
--- a/cmd/git-chglog/kac_template_builder.go
+++ b/cmd/git-chglog/kac_template_builder.go
@@ -47,7 +47,7 @@ func (t *kacTemplateBuilderImpl) versionHeader(style string) string {
)
switch style {
- case styleGitHub, styleGitLab:
+ case styleGitHub, styleGitLab, styleBitbucket:
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]{{else}}{{.Tag.Name}}{{end}}"
}
@@ -85,7 +85,7 @@ func (t *kacTemplateBuilderImpl) merges(style string) string {
var title string
switch style {
- case styleGitHub:
+ case styleGitHub, styleBitbucket:
title = "Pull Requests"
case styleGitLab:
title = "Merge Requests"
@@ -114,6 +114,11 @@ func (*kacTemplateBuilderImpl) footer(style string) string {
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}}`
+ case styleBitbucket:
+ return `{{if .Versions}}
+[Unreleased]: {{.Info.RepositoryURL}}/compare/HEAD..{{$latest := index .Versions 0}}{{$latest.Tag.Name}}{{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/processor_factory.go b/cmd/git-chglog/processor_factory.go
index 7122c4a3..2d8fb32e 100644
--- a/cmd/git-chglog/processor_factory.go
+++ b/cmd/git-chglog/processor_factory.go
@@ -16,8 +16,9 @@ type ProcessorFactory struct {
func NewProcessorFactory() *ProcessorFactory {
return &ProcessorFactory{
hostRegistry: map[string]string{
- "github": "github.com",
- "gitlab": "gitlab.com",
+ "github": "github.com",
+ "gitlab": "gitlab.com",
+ "bitbucket": "bitbucket.org",
},
}
}
@@ -46,6 +47,10 @@ func (factory *ProcessorFactory) Create(config *Config) (chglog.Processor, error
return &chglog.GitLabProcessor{
Host: fmt.Sprintf("%s://%s", obj.Scheme, obj.Host),
}, nil
+ case "bitbucket.org":
+ return &chglog.BitbucketProcessor{
+ Host: fmt.Sprintf("%s://%s", obj.Scheme, obj.Host),
+ }, nil
default:
return nil, nil
}
diff --git a/cmd/git-chglog/processor_factory_test.go b/cmd/git-chglog/processor_factory_test.go
index 32fd1234..f9d5c5bc 100644
--- a/cmd/git-chglog/processor_factory_test.go
+++ b/cmd/git-chglog/processor_factory_test.go
@@ -92,3 +92,39 @@ func TestProcessorFactoryForGitLab(t *testing.T) {
processor,
)
}
+
+func TestProcessorFactoryForBitbucket(t *testing.T) {
+ assert := assert.New(t)
+ factory := NewProcessorFactory()
+
+ // bitbucket.org
+ processor, err := factory.Create(&Config{
+ Info: Info{
+ RepositoryURL: "https://bitbucket.org/owner/repo",
+ },
+ })
+
+ assert.Nil(err)
+ assert.Equal(
+ &chglog.BitbucketProcessor{
+ Host: "https://bitbucket.org",
+ },
+ processor,
+ )
+
+ // self-hosted
+ processor, err = factory.Create(&Config{
+ Style: "bitbucket",
+ Info: Info{
+ RepositoryURL: "https://original-gitserver.com/owner/repo",
+ },
+ })
+
+ assert.Nil(err)
+ assert.Equal(
+ &chglog.BitbucketProcessor{
+ Host: "https://original-gitserver.com",
+ },
+ processor,
+ )
+}
diff --git a/cmd/git-chglog/variables.go b/cmd/git-chglog/variables.go
index 92132c3f..cfb90c79 100644
--- a/cmd/git-chglog/variables.go
+++ b/cmd/git-chglog/variables.go
@@ -14,12 +14,14 @@ var (
// Styles
var (
- styleGitHub = "github"
- styleGitLab = "gitlab"
- styleNone = "none"
- styles = []string{
+ styleGitHub = "github"
+ styleGitLab = "gitlab"
+ styleBitbucket = "bitbucket"
+ styleNone = "none"
+ styles = []string{
styleGitHub,
styleGitLab,
+ styleBitbucket,
styleNone,
}
)
diff --git a/processor.go b/processor.go
index d5da974f..9b46d387 100644
--- a/processor.go
+++ b/processor.go
@@ -120,3 +120,58 @@ func (p *GitLabProcessor) addLinks(input string) string {
return input
}
+
+// BitbucketProcessor is optimized for CHANGELOG used in Bitbucket
+//
+// The following processing is performed
+// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://bitbucket.org/tsuyoshiwada/))
+// - Automatic link to references (#123 -> [#123](https://bitbucket.org/owner/repo/issues/123/))
+type BitbucketProcessor struct {
+ Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://bitbucket.org")
+ config *Config
+ reMention *regexp.Regexp
+ reIssue *regexp.Regexp
+}
+
+// Bootstrap ...
+func (p *BitbucketProcessor) Bootstrap(config *Config) {
+ p.config = config
+
+ if p.Host == "" {
+ p.Host = "https://bitbucket.org"
+ } else {
+ p.Host = strings.TrimRight(p.Host, "/")
+ }
+
+ p.reMention = regexp.MustCompile("@(\\w+)")
+ p.reIssue = regexp.MustCompile("(?i)#(\\d+)")
+}
+
+// ProcessCommit ...
+func (p *BitbucketProcessor) ProcessCommit(commit *Commit) *Commit {
+ commit.Header = p.addLinks(commit.Header)
+ commit.Subject = p.addLinks(commit.Subject)
+ commit.Body = p.addLinks(commit.Body)
+
+ for _, note := range commit.Notes {
+ note.Body = p.addLinks(note.Body)
+ }
+
+ if commit.Revert != nil {
+ commit.Revert.Header = p.addLinks(commit.Revert.Header)
+ }
+
+ return commit
+}
+
+func (p *BitbucketProcessor) addLinks(input string) string {
+ repoURL := strings.TrimRight(p.config.Info.RepositoryURL, "/")
+
+ // mentions
+ input = p.reMention.ReplaceAllString(input, "[@$1]("+p.Host+"/$1/)")
+
+ // issues
+ input = p.reIssue.ReplaceAllString(input, "[#$1]("+repoURL+"/issues/$1/)")
+
+ return input
+}
diff --git a/processor_test.go b/processor_test.go
index 4a80b4b6..177f1506 100644
--- a/processor_test.go
+++ b/processor_test.go
@@ -129,3 +129,65 @@ gh-56 hoge fuga`,
),
)
}
+
+func TestBitbucketProcessor(t *testing.T) {
+ assert := assert.New(t)
+
+ config := &Config{
+ Info: &Info{
+ RepositoryURL: "https://example.com",
+ },
+ }
+
+ processor := &BitbucketProcessor{}
+
+ processor.Bootstrap(config)
+
+ assert.Equal(
+ &Commit{
+ Header: "message [@foo](https://bitbucket.org/foo/) [#123](https://example.com/issues/123/)",
+ Subject: "message [@foo](https://bitbucket.org/foo/) [#123](https://example.com/issues/123/)",
+ Body: `issue [#456](https://example.com/issues/456/)
+multiline [#789](https://example.com/issues/789/)
+[@foo](https://bitbucket.org/foo/), [@bar](https://bitbucket.org/bar/)`,
+ Notes: []*Note{
+ &Note{
+ Body: `issue1 [#11](https://example.com/issues/11/)
+issue2 [#22](https://example.com/issues/22/)
+gh-56 hoge fuga`,
+ },
+ },
+ },
+ processor.ProcessCommit(
+ &Commit{
+ Header: "message @foo #123",
+ Subject: "message @foo #123",
+ Body: `issue #456
+multiline #789
+@foo, @bar`,
+ Notes: []*Note{
+ &Note{
+ Body: `issue1 #11
+issue2 #22
+gh-56 hoge fuga`,
+ },
+ },
+ },
+ ),
+ )
+
+ assert.Equal(
+ &Commit{
+ Revert: &Revert{
+ Header: "revert header [@mention](https://bitbucket.org/mention/) [#123](https://example.com/issues/123/)",
+ },
+ },
+ processor.ProcessCommit(
+ &Commit{
+ Revert: &Revert{
+ Header: "revert header @mention #123",
+ },
+ },
+ ),
+ )
+}