From 44f71cbcd8740ba7c2e38c5ff7d0a38d2d3e7f02 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Sat, 9 Jan 2021 17:11:18 -0500 Subject: [PATCH] feat: Adds 'Custom' sort_type to CommitGroup (#69) Closes #60 --- README.md | 15 +++-- chglog.go | 37 +++++------ cmd/git-chglog/config.go | 42 +++++++------ commit_extractor.go | 11 ++++ commit_extractor_test.go | 131 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 192 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 0b98c4e5..8c3a90f1 100644 --- a/README.md +++ b/README.md @@ -235,6 +235,8 @@ options: commit_groups: group_by: Type sort_by: Title + title_order: + - feat title_maps: feat: Features @@ -317,11 +319,12 @@ Options concerning the acquisition and sort of commits. Options for groups of commits. -| Key | Required | Type | Default | Description | -|:-------------|:---------|:------------|:----------|:-------------------------------------------------------------------------------------------| -| `group_by` | N | String | `"Type"` | Property name of `Commit` to be grouped into `CommitGroup`. See [CommitGroup][doc-commit]. | -| `sort_by` | N | String | `"Title"` | Property name to use for sorting `CommitGroup`. See [CommitGroup][doc-commit-group]. | -| `title_maps` | N | Map in List | none | Map for `CommitGroup` title conversion. | +| Key | Required | Type | Default | Description | +|:--------------|:---------|:------------|:----------|:-------------------------------------------------------------------------------------------| +| `group_by` | N | String | `"Type"` | Property name of `Commit` to be grouped into `CommitGroup`. See [CommitGroup][doc-commit]. | +| `sort_by` | N | String | `"Title"` | Property name to use for sorting `CommitGroup`. See [CommitGroup][doc-commit-group]. | +| `title_order` | N | List | none | Predefined order of titles to use for sorting `CommitGroup`. Only if `sort_by` is `Custom` | +| `title_maps` | N | Map in List | none | Map for `CommitGroup` title conversion. | #### `options.header` @@ -549,6 +552,6 @@ See [CHANGELOG.md](./CHANGELOG.md) [MIT © tsuyoshiwada](./LICENSE) [doc-commit]: https://godoc.org/github.com/git-chglog/git-chglog#Commit -[doc-commit-group]: https://godoc.org/github.com/git-chglog/git-chglog#Commit +[doc-commit-group]: https://godoc.org/github.com/git-chglog/git-chglog#CommitGroup [doc-ref]: https://godoc.org/github.com/git-chglog/git-chglog#Ref [doc-render-data]: https://godoc.org/github.com/git-chglog/git-chglog#RenderData diff --git a/chglog.go b/chglog.go index 1e58c587..d0afac53 100644 --- a/chglog.go +++ b/chglog.go @@ -16,24 +16,25 @@ import ( // Options is an option used to process commits type Options struct { - Processor Processor - NextTag string // Treat unreleased commits as specified tags (EXPERIMENTAL) - TagFilterPattern string // Filter tag by regexp - NoCaseSensitive bool // Filter commits in a case insensitive way - CommitFilters map[string][]string // Filter by using `Commit` properties and values. Filtering is not done by specifying an empty value - CommitSortBy string // Property name to use for sorting `Commit` (e.g. `Scope`) - CommitGroupBy string // Property name of `Commit` to be grouped into `CommitGroup` (e.g. `Type`) - CommitGroupSortBy string // Property name to use for sorting `CommitGroup` (e.g. `Title`) - CommitGroupTitleMaps map[string]string // Map for `CommitGroup` title conversion - HeaderPattern string // A regular expression to use for parsing the commit header - HeaderPatternMaps []string // A rule for mapping the result of `HeaderPattern` to the property of `Commit` - IssuePrefix []string // Prefix used for issues (e.g. `#`, `gh-`) - RefActions []string // Word list of `Ref.Action` - MergePattern string // A regular expression to use for parsing the merge commit - MergePatternMaps []string // Similar to `HeaderPatternMaps` - RevertPattern string // A regular expression to use for parsing the revert commit - RevertPatternMaps []string // Similar to `HeaderPatternMaps` - NoteKeywords []string // Keyword list to find `Note`. A semicolon is a separator, like `:` (e.g. `BREAKING CHANGE`) + Processor Processor + NextTag string // Treat unreleased commits as specified tags (EXPERIMENTAL) + TagFilterPattern string // Filter tag by regexp + NoCaseSensitive bool // Filter commits in a case insensitive way + CommitFilters map[string][]string // Filter by using `Commit` properties and values. Filtering is not done by specifying an empty value + CommitSortBy string // Property name to use for sorting `Commit` (e.g. `Scope`) + CommitGroupBy string // Property name of `Commit` to be grouped into `CommitGroup` (e.g. `Type`) + CommitGroupSortBy string // Property name to use for sorting `CommitGroup` (e.g. `Title`) + CommitGroupTitleOrder []string // Predefined sorted list of titles to use for sorting `CommitGroup`. Only if `CommitGroupSortBy` is `Custom` + CommitGroupTitleMaps map[string]string // Map for `CommitGroup` title conversion + HeaderPattern string // A regular expression to use for parsing the commit header + HeaderPatternMaps []string // A rule for mapping the result of `HeaderPattern` to the property of `Commit` + IssuePrefix []string // Prefix used for issues (e.g. `#`, `gh-`) + RefActions []string // Word list of `Ref.Action` + MergePattern string // A regular expression to use for parsing the merge commit + MergePatternMaps []string // Similar to `HeaderPatternMaps` + RevertPattern string // A regular expression to use for parsing the revert commit + RevertPatternMaps []string // Similar to `HeaderPatternMaps` + NoteKeywords []string // Keyword list to find `Note`. A semicolon is a separator, like `:` (e.g. `BREAKING CHANGE`) } // Info is metadata related to CHANGELOG diff --git a/cmd/git-chglog/config.go b/cmd/git-chglog/config.go index bd48b691..7baeca4a 100644 --- a/cmd/git-chglog/config.go +++ b/cmd/git-chglog/config.go @@ -22,9 +22,10 @@ type CommitOptions struct { // CommitGroupOptions ... type CommitGroupOptions struct { - GroupBy string `yaml:"group_by"` - SortBy string `yaml:"sort_by"` - TitleMaps map[string]string `yaml:"title_maps"` + GroupBy string `yaml:"group_by"` + SortBy string `yaml:"sort_by"` + TitleOrder []string `yaml:"title_order"` + TitleMaps map[string]string `yaml:"title_maps"` } // PatternOptions ... @@ -262,23 +263,24 @@ func (config *Config) Convert(ctx *CLIContext) *chglog.Config { RepositoryURL: info.RepositoryURL, }, Options: &chglog.Options{ - NextTag: ctx.NextTag, - TagFilterPattern: ctx.TagFilterPattern, - NoCaseSensitive: ctx.NoCaseSensitive, - CommitFilters: opts.Commits.Filters, - CommitSortBy: opts.Commits.SortBy, - CommitGroupBy: opts.CommitGroups.GroupBy, - CommitGroupSortBy: opts.CommitGroups.SortBy, - CommitGroupTitleMaps: opts.CommitGroups.TitleMaps, - HeaderPattern: opts.Header.Pattern, - HeaderPatternMaps: opts.Header.PatternMaps, - IssuePrefix: opts.Issues.Prefix, - RefActions: opts.Refs.Actions, - MergePattern: opts.Merges.Pattern, - MergePatternMaps: opts.Merges.PatternMaps, - RevertPattern: opts.Reverts.Pattern, - RevertPatternMaps: opts.Reverts.PatternMaps, - NoteKeywords: opts.Notes.Keywords, + NextTag: ctx.NextTag, + TagFilterPattern: ctx.TagFilterPattern, + NoCaseSensitive: ctx.NoCaseSensitive, + CommitFilters: opts.Commits.Filters, + CommitSortBy: opts.Commits.SortBy, + CommitGroupBy: opts.CommitGroups.GroupBy, + CommitGroupSortBy: opts.CommitGroups.SortBy, + CommitGroupTitleMaps: opts.CommitGroups.TitleMaps, + CommitGroupTitleOrder: opts.CommitGroups.TitleOrder, + HeaderPattern: opts.Header.Pattern, + HeaderPatternMaps: opts.Header.PatternMaps, + IssuePrefix: opts.Issues.Prefix, + RefActions: opts.Refs.Actions, + MergePattern: opts.Merges.Pattern, + MergePatternMaps: opts.Merges.PatternMaps, + RevertPattern: opts.Reverts.Pattern, + RevertPatternMaps: opts.Reverts.PatternMaps, + NoteKeywords: opts.Notes.Keywords, }, } } diff --git a/commit_extractor.go b/commit_extractor.go index 610897b2..ea1b2996 100644 --- a/commit_extractor.go +++ b/commit_extractor.go @@ -128,8 +128,19 @@ func (e *commitExtractor) commitGroupTitle(commit *Commit) (string, string) { } func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) { + order := make(map[string]int) + if e.opts.CommitGroupSortBy == "Custom" { + for i, t := range e.opts.CommitGroupTitleOrder { + order[t] = i + } + } + // groups sort.Slice(groups, func(i, j int) bool { + if e.opts.CommitGroupSortBy == "Custom" { + return order[groups[i].RawTitle] < order[groups[j].RawTitle] + } + var ( a, b interface{} ok bool diff --git a/commit_extractor_test.go b/commit_extractor_test.go index 59f80dce..5e251b3c 100644 --- a/commit_extractor_test.go +++ b/commit_extractor_test.go @@ -135,3 +135,134 @@ func TestCommitExtractor(t *testing.T) { }, }, noteGroups) } + +func TestCommitOrderExtractor(t *testing.T) { + assert := assert.New(t) + + extractor := newCommitExtractor(&Options{ + CommitSortBy: "Scope", + CommitGroupBy: "Type", + CommitGroupSortBy: "Custom", + CommitGroupTitleOrder: []string{"foo", "bar"}, + CommitGroupTitleMaps: map[string]string{ + "bar": "BAR", + }, + }) + + fixtures := []*Commit{ + // [0] + { + Type: "foo", + Scope: "c", + Header: "1", + Notes: []*Note{}, + }, + // [1] + { + Type: "foo", + Scope: "b", + Header: "2", + Notes: []*Note{ + {"note1-title", "note1-body"}, + {"note2-title", "note2-body"}, + }, + }, + // [2] + { + Type: "bar", + Scope: "d", + Header: "3", + Notes: []*Note{ + {"note1-title", "note1-body"}, + {"note3-title", "note3-body"}, + }, + }, + // [3] + { + Type: "foo", + Scope: "a", + Header: "4", + Notes: []*Note{ + {"note4-title", "note4-body"}, + }, + }, + // [4] + { + Type: "", + Scope: "", + Header: "Merge1", + Notes: []*Note{}, + Merge: &Merge{ + Ref: "123", + Source: "merges/merge1", + }, + }, + // [5] + { + Type: "", + Scope: "", + Header: "Revert1", + Notes: []*Note{}, + Revert: &Revert{ + Header: "REVERT1", + }, + }, + } + + commitGroups, mergeCommits, revertCommits, noteGroups := extractor.Extract(fixtures) + + assert.Equal([]*CommitGroup{ + { + RawTitle: "foo", + Title: "Foo", + Commits: []*Commit{ + fixtures[3], + fixtures[1], + fixtures[0], + }, + }, + { + RawTitle: "bar", + Title: "BAR", + Commits: []*Commit{ + fixtures[2], + }, + }, + }, commitGroups) + + assert.Equal([]*Commit{ + fixtures[4], + }, mergeCommits) + + assert.Equal([]*Commit{ + fixtures[5], + }, revertCommits) + + assert.Equal([]*NoteGroup{ + { + Title: "note1-title", + Notes: []*Note{ + fixtures[1].Notes[0], + fixtures[2].Notes[0], + }, + }, + { + Title: "note2-title", + Notes: []*Note{ + fixtures[1].Notes[1], + }, + }, + { + Title: "note3-title", + Notes: []*Note{ + fixtures[2].Notes[1], + }, + }, + { + Title: "note4-title", + Notes: []*Note{ + fixtures[3].Notes[0], + }, + }, + }, noteGroups) +}