From f4d149933193186889b5a427153eb6bd74791761 Mon Sep 17 00:00:00 2001 From: Beatriz Vieira Date: Sat, 1 Feb 2020 22:40:31 -0300 Subject: [PATCH] refactor: extract template operation to formatter struct --- cmd/git-sv/handlers.go | 6 ++--- cmd/git-sv/main.go | 5 ++-- sv/formatter.go | 59 ++++++++++++++++++++++++++++++++++++++++++ sv/releasenotes.go | 46 ++------------------------------ 4 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 sv/formatter.go diff --git a/cmd/git-sv/handlers.go b/cmd/git-sv/handlers.go index f6da003..ebde62b 100644 --- a/cmd/git-sv/handlers.go +++ b/cmd/git-sv/handlers.go @@ -76,7 +76,7 @@ func getTagCommits(git sv.Git, tag string) ([]sv.GitCommitLog, error) { return git.Log(prev, tag) } -func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnProcessor sv.ReleaseNoteProcessor) func(c *cli.Context) error { +func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnProcessor sv.ReleaseNoteProcessor, outputFormatter sv.OutputFormatter) func(c *cli.Context) error { return func(c *cli.Context) error { var commits []sv.GitCommitLog var rnVersion semver.Version @@ -94,7 +94,7 @@ func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, } releasenote := rnProcessor.Create(rnVersion, date, commits) - fmt.Println(rnProcessor.Format(releasenote)) + fmt.Println(outputFormatter.FormatReleaseNote(releasenote)) return nil } } @@ -161,7 +161,7 @@ func getNextVersionInfo(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) ( return semverProcessor.NextVersion(currentVer, commits), time.Now(), commits, nil } -func tagHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnProcessor sv.ReleaseNoteProcessor) func(c *cli.Context) error { +func tagHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error { return func(c *cli.Context) error { describe := git.Describe() diff --git a/cmd/git-sv/main.go b/cmd/git-sv/main.go index 67c8e20..2380f27 100644 --- a/cmd/git-sv/main.go +++ b/cmd/git-sv/main.go @@ -17,6 +17,7 @@ func main() { git := sv.NewGit(cfg.BreakingChangePrefixes, cfg.IssueIDPrefixes, cfg.TagPattern) semverProcessor := sv.NewSemVerCommitsProcessor(cfg.IncludeUnknownTypeAsPatch, cfg.MajorVersionTypes, cfg.MinorVersionTypes, cfg.PatchVersionTypes) releasenotesProcessor := sv.NewReleaseNoteProcessor(cfg.ReleaseNotesTags) + outputFormatter := sv.NewOutputFormatter() app := cli.NewApp() app.Name = "sv" @@ -46,14 +47,14 @@ func main() { Name: "release-notes", Aliases: []string{"rn"}, Usage: "generate release notes", - Action: releaseNotesHandler(git, semverProcessor, releasenotesProcessor), + Action: releaseNotesHandler(git, semverProcessor, releasenotesProcessor, outputFormatter), Flags: []cli.Flag{&cli.StringFlag{Name: "t", Usage: "get release note from tag"}}, }, { Name: "tag", Aliases: []string{"tg"}, Usage: "generate tag with version based on git commit messages", - Action: tagHandler(git, semverProcessor, releasenotesProcessor), + Action: tagHandler(git, semverProcessor), }, } diff --git a/sv/formatter.go b/sv/formatter.go new file mode 100644 index 0000000..b9d0d70 --- /dev/null +++ b/sv/formatter.go @@ -0,0 +1,59 @@ +package sv + +import ( + "bytes" + "fmt" + "text/template" +) + +type releaseNoteTemplateVariables struct { + Version string + Date string + Sections map[string]ReleaseNoteSection + BreakingChanges []string +} + +const rnTemplate = `## v{{.Version}} ({{.Date}}) + +{{if .Sections.feat}}### {{.Sections.feat.Name}} +{{range $k,$v := .Sections.feat.Items}} +- {{if $v.Scope}}**{{$v.Scope}}:** {{end}}{{$v.Subject}} ({{$v.Hash}}) {{if $v.Metadata.issueid}}({{$v.Metadata.issueid}}){{end}}{{end}}{{end}} + +{{if .Sections.fix}}### {{.Sections.fix.Name}} +{{range $k,$v := .Sections.fix.Items}} +- {{if $v.Scope}}**{{$v.Scope}}:** {{end}}{{$v.Subject}} ({{$v.Hash}}) {{if $v.Metadata.issueid}}({{$v.Metadata.issueid}}){{end}}{{end}}{{end}} + +{{if .BreakingChanges}}### Breaking Changes +{{range $k,$v := .BreakingChanges}} +- {{$v}}{{end}} +{{end}}` + +// OutputFormatter output formatter interface. +type OutputFormatter interface { + FormatReleaseNote(releasenote ReleaseNote) string +} + +// OutputFormatterImpl formater for release note and changelog. +type OutputFormatterImpl struct { + releasenoteTemplate *template.Template +} + +// NewOutputFormatter TemplateProcessor constructor. +func NewOutputFormatter() *OutputFormatterImpl { + template := template.Must(template.New("releasenotes").Parse(rnTemplate)) + return &OutputFormatterImpl{releasenoteTemplate: template} +} + +// FormatReleaseNote format a release note. +func (p OutputFormatterImpl) FormatReleaseNote(releasenote ReleaseNote) string { + templateVars := releaseNoteTemplateVariables{ + Version: fmt.Sprintf("%d.%d.%d", releasenote.Version.Major(), releasenote.Version.Minor(), releasenote.Version.Patch()), + Date: releasenote.Date.Format("2006-01-02"), + Sections: releasenote.Sections, + BreakingChanges: releasenote.BreakingChanges, + } + + var b bytes.Buffer + p.releasenoteTemplate.Execute(&b, templateVars) + return b.String() +} diff --git a/sv/releasenotes.go b/sv/releasenotes.go index 8b7ed08..9a30f41 100644 --- a/sv/releasenotes.go +++ b/sv/releasenotes.go @@ -1,52 +1,24 @@ package sv import ( - "bytes" - "fmt" - "text/template" "time" "github.com/Masterminds/semver" ) -type releaseNoteTemplate struct { - Version string - Date string - Sections map[string]ReleaseNoteSection - BreakingChanges []string -} - -const markdownTemplate = `## v{{.Version}} ({{.Date}}) - -{{if .Sections.feat}}### {{.Sections.feat.Name}} -{{range $k,$v := .Sections.feat.Items}} -- {{if $v.Scope}}**{{$v.Scope}}:** {{end}}{{$v.Subject}} ({{$v.Hash}}) {{if $v.Metadata.issueid}}({{$v.Metadata.issueid}}){{end}}{{end}}{{end}} - -{{if .Sections.fix}}### {{.Sections.fix.Name}} -{{range $k,$v := .Sections.fix.Items}} -- {{if $v.Scope}}**{{$v.Scope}}:** {{end}}{{$v.Subject}} ({{$v.Hash}}) {{if $v.Metadata.issueid}}({{$v.Metadata.issueid}}){{end}}{{end}}{{end}} - -{{if .BreakingChanges}}### Breaking Changes -{{range $k,$v := .BreakingChanges}} -- {{$v}}{{end}} -{{end}}` - // ReleaseNoteProcessor release note processor interface. type ReleaseNoteProcessor interface { Create(version semver.Version, date time.Time, commits []GitCommitLog) ReleaseNote - Format(releasenote ReleaseNote) string } // ReleaseNoteProcessorImpl release note based on commit log. type ReleaseNoteProcessorImpl struct { - tags map[string]string - template *template.Template + tags map[string]string } // NewReleaseNoteProcessor ReleaseNoteProcessor constructor. func NewReleaseNoteProcessor(tags map[string]string) *ReleaseNoteProcessorImpl { - template := template.Must(template.New("markdown").Parse(markdownTemplate)) - return &ReleaseNoteProcessorImpl{tags: tags, template: template} + return &ReleaseNoteProcessorImpl{tags: tags} } // Create create a release note based on commits. @@ -70,20 +42,6 @@ func (p ReleaseNoteProcessorImpl) Create(version semver.Version, date time.Time, return ReleaseNote{Version: version, Date: date.Truncate(time.Minute), Sections: sections, BreakingChanges: breakingChanges} } -// Format format a release note. -func (p ReleaseNoteProcessorImpl) Format(releasenote ReleaseNote) string { - templateVars := releaseNoteTemplate{ - Version: fmt.Sprintf("%d.%d.%d", releasenote.Version.Major(), releasenote.Version.Minor(), releasenote.Version.Patch()), - Date: releasenote.Date.Format("2006-01-02"), - Sections: releasenote.Sections, - BreakingChanges: releasenote.BreakingChanges, - } - - var b bytes.Buffer - p.template.Execute(&b, templateVars) - return b.String() -} - // ReleaseNote release note. type ReleaseNote struct { Version semver.Version