From d55318c7a09aaab32c6c010cdb8e5d2823818d13 Mon Sep 17 00:00:00 2001 From: tsuyoshiwada Date: Sun, 18 Feb 2018 01:54:44 +0900 Subject: [PATCH] docs: Add godoc --- chglog.go | 62 +++++++++++++++++++++------------------ chglog_test.go | 4 +-- cmd/git-chglog/main.go | 11 ++++--- errors.go | 7 +++++ example_test.go | 66 ++++++++++++++++++++++++++++++++++++++++++ fields.go | 48 +++++++++++++++--------------- processor.go | 21 +++++--------- tag_selector.go | 15 +++------- utils.go | 4 +-- 9 files changed, 154 insertions(+), 84 deletions(-) create mode 100644 example_test.go diff --git a/chglog.go b/chglog.go index a4a0a5a9..ac4e4f61 100644 --- a/chglog.go +++ b/chglog.go @@ -1,3 +1,4 @@ +// Package chglog implements main logic for the CHANGELOG generate. package chglog import ( @@ -11,42 +12,42 @@ import ( gitcmd "github.com/tsuyoshiwada/go-gitcmd" ) -// Options ... +// Options is an option used to process commits type Options struct { Processor Processor - CommitFilters map[string][]string - CommitSortBy string - CommitGroupBy string - CommitGroupSortBy string - CommitGroupTitleMaps map[string]string - HeaderPattern string - HeaderPatternMaps []string - IssuePrefix []string - RefActions []string - MergePattern string - MergePatternMaps []string - RevertPattern string - RevertPatternMaps []string - NoteKeywords []string + 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`) } -// Info ... +// Info is metadata related to CHANGELOG type Info struct { - Title string - RepositoryURL string + Title string // Title of CHANGELOG + RepositoryURL string // URL of git repository } -// RenderData ... +// RenderData is the data passed to the template type RenderData struct { Info *Info Versions []*Version } -// Config ... +// Config for generating CHANGELOG type Config struct { - Bin string - WorkingDir string - Template string + Bin string // Git execution command + WorkingDir string // Working directory + Template string // Path for template file. If a relative path is specified, it depends on the value of `WorkingDir`. Info *Info Options *Options } @@ -78,7 +79,7 @@ func normalizeConfig(config *Config) { config.Options = opts } -// Generator ... +// Generator of CHANGELOG type Generator struct { client gitcmd.Client config *Config @@ -88,7 +89,7 @@ type Generator struct { commitExtractor *commitExtractor } -// NewGenerator ... +// NewGenerator receives `Config` and create an new `Generator` func NewGenerator(config *Config) *Generator { client := gitcmd.New(&gitcmd.Config{ Bin: config.Bin, @@ -110,20 +111,25 @@ func NewGenerator(config *Config) *Generator { } } -// Generate ... +// Generate gets the commit based on the specified tag `query` and writes the result to `io.Writer` +// +// tag `query` can be specified with the following rule +// .. - Commit contained in `` tags from `` (e.g. `1.0.0..2.0.0`) +// .. - Commit from the `` to the latest tag (e.g. `1.0.0..`) +// .. - Commit from the oldest tag to `` (e.g. `..1.0.0`) +// - Commit contained in `` (e.g. `1.0.0`) func (gen *Generator) Generate(w io.Writer, query string) error { back, err := gen.workdir() if err != nil { return err } + defer back() versions, err := gen.readVersions(query) if err != nil { return err } - back() - return gen.render(w, versions) } diff --git a/chglog_test.go b/chglog_test.go index 43821a72..586460ac 100644 --- a/chglog_test.go +++ b/chglog_test.go @@ -55,7 +55,7 @@ func TestGeneratorNotFoundCommits(t *testing.T) { gen := NewGenerator(&Config{ Bin: "git", WorkingDir: filepath.Join(testRepoRoot, testName), - Template: filepath.Join("testdata", testName+".md"), + Template: filepath.Join(cwd, "testdata", testName+".md"), Info: &Info{ RepositoryURL: "https://github.com/git-chglog/git-chglog", }, @@ -124,7 +124,7 @@ func TestGeneratorWithTypeScopeSubject(t *testing.T) { gen := NewGenerator(&Config{ Bin: "git", WorkingDir: filepath.Join(testRepoRoot, testName), - Template: filepath.Join("testdata", testName+".md"), + Template: filepath.Join(cwd, "testdata", testName+".md"), Info: &Info{ Title: "CHANGELOG Example", RepositoryURL: "https://github.com/git-chglog/git-chglog", diff --git a/cmd/git-chglog/main.go b/cmd/git-chglog/main.go index ef182220..a2faca12 100644 --- a/cmd/git-chglog/main.go +++ b/cmd/git-chglog/main.go @@ -25,10 +25,13 @@ func main() { {{range .Flags}}{{.}} {{end}} %s - {{.Name}} todo1 - {{.Name}} todo2 - {{.Name}} todo3 - {{.Name}} todo4 + {{.Name}} + {{.Name}} 1.0.0..5.0.0-rc.10 + {{.Name}} 1.0.0.. + {{.Name}} ..5.0.0-rc.10 + {{.Name}} 1.0.0 + {{.Name}} --output CHANGELOG.md + {{.Name}} --config dir/path/config.yml `, ttl("USAGE:"), ttl("VERSION:"), diff --git a/errors.go b/errors.go index 38950c8b..e1595153 100644 --- a/errors.go +++ b/errors.go @@ -1 +1,8 @@ package chglog + +import "errors" + +var ( + errNotFoundTag = errors.New("could not find the tag") + errFailedQueryParse = errors.New("failed to parse the query") +) diff --git a/example_test.go b/example_test.go new file mode 100644 index 00000000..fd0f1adb --- /dev/null +++ b/example_test.go @@ -0,0 +1,66 @@ +package chglog + +import ( + "bytes" + "fmt" + "log" +) + +func Example() { + gen := NewGenerator(&Config{ + Bin: "git", + WorkingDir: ".", + Template: "CHANGELOG.tpl.md", + Info: &Info{ + Title: "CHANGELOG", + RepositoryURL: "https://github.com/git-chglog/git-chglog", + }, + Options: &Options{ + CommitFilters: map[string][]string{ + "Type": []string{ + "feat", + "fix", + }, + }, + CommitSortBy: "Scope", + CommitGroupBy: "Type", + CommitGroupSortBy: "Title", + CommitGroupTitleMaps: map[string]string{ + "feat": "Features", + "fix": "Bug Fixes", + }, + HeaderPattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$", + HeaderPatternMaps: []string{ + "Type", + "Scope", + "Subject", + }, + IssuePrefix: []string{ + "#", + "gh-", + }, + RefActions: []string{}, + MergePattern: "^Merge pull request #(\\d+) from (.*)$", + MergePatternMaps: []string{ + "Ref", + "Source", + }, + RevertPattern: "^Revert \"([\\s\\S]*)\"$", + RevertPatternMaps: []string{ + "Header", + }, + NoteKeywords: []string{ + "BREAKING CHANGE", + }, + }, + }) + + buf := &bytes.Buffer{} + err := gen.Generate(buf, "") + + if err != nil { + log.Fatalln(err) + } + + fmt.Println(buf.String()) +} diff --git a/fields.go b/fields.go index a348aba6..1ad9b743 100644 --- a/fields.go +++ b/fields.go @@ -22,31 +22,31 @@ type Committer struct { Date time.Time } -// Merge ... +// Merge info for commit type Merge struct { Ref string Source string } -// Revert ... +// Revert info for commit type Revert struct { Header string } -// Ref ... +// Ref is abstract data related to commit. (e.g. `Issues`, `Pull Request`) type Ref struct { - Action string - Ref string - Source string + Action string // (e.g. `Closes`) + Ref string // (e.g. `123`) + Source string // (e.g. `owner/repository`) } -// Note ... +// Note of commit type Note struct { - Title string - Body string + Title string // (e.g. `BREAKING CHANGE`) + Body string // `Note` content body } -// NoteGroup ... +// NoteGroup is a collection of `Note` grouped by titles type NoteGroup struct { Title string Notes []*Note @@ -57,32 +57,34 @@ type Commit struct { Hash *Hash Author *Author Committer *Committer - Merge *Merge - Revert *Revert + Merge *Merge // If it is not a merge commit, `nil` is assigned + Revert *Revert // If it is not a revert commit, `nil` is assigned Refs []*Ref Notes []*Note - Mentions []string - Header string - Type string - Scope string - Subject string + Mentions []string // Name of the user included in the commit header or body + Header string // (e.g. `feat(core): Add new feature`) + Type string // (e.g. `feat`) + Scope string // (e.g. `core`) + Subject string // (e.g. `Add new feature`) Body string } -// CommitGroup is group of commit +// CommitGroup is a collection of commits grouped according to the `CommitGroupBy` option type CommitGroup struct { - RawTitle string - Title string + RawTitle string // Raw title before conversion (e.g. `build`) + Title string // Conversion by `CommitGroupTitleMaps` option, or title converted in title case (e.g. `Build`) Commits []*Commit } -// RelateTag ... +// RelateTag is sibling tag data of `Tag`. +// If you give `Tag`, the reference hierarchy will be deepened. +// This struct is used to minimize the hierarchy of references type RelateTag struct { Name string Date time.Time } -// Tag ... +// Tag is data of git-tag type Tag struct { Name string Date time.Time @@ -90,7 +92,7 @@ type Tag struct { Previous *RelateTag } -// Version ... +// Version is a tag-separeted datset to be included in CHANGELOG type Version struct { Tag *Tag CommitGroups []*CommitGroup diff --git a/processor.go b/processor.go index 9cd65bf7..5fef2dae 100644 --- a/processor.go +++ b/processor.go @@ -5,26 +5,19 @@ import ( "strings" ) -// Processor ... +// Processor hooks the internal processing of `Generator`, it is possible to adjust the contents type Processor interface { Bootstrap(*Config) ProcessCommit(*Commit) *Commit } -// PlainProcessor ... -type PlainProcessor struct{} - -// Bootstrap ... -func (*PlainProcessor) Bootstrap(config *Config) {} - -// ProcessCommit ... -func (*PlainProcessor) ProcessCommit(commit *Commit) *Commit { - return commit -} - -// GitHubProcessor ... +// GitHubProcessor is optimized for CHANGELOG used in GitHub +// +// The following processing is performed +// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://github.com/tsuyoshiwada)) +// - Automatic link to references (#123 -> [#123](https://github.com/owner/repo/issues/123)) type GitHubProcessor struct { - Host string + Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://github.com") config *Config reMention *regexp.Regexp reIssue *regexp.Regexp diff --git a/tag_selector.go b/tag_selector.go index 6b821d73..fe17a505 100644 --- a/tag_selector.go +++ b/tag_selector.go @@ -1,16 +1,9 @@ package chglog import ( - "errors" "strings" ) -// TODO -var ( - errNotFound = errors.New("todo: not found") - errParse = errors.New("todo: parse error") -) - type tagSelector struct{} func newTagSelector() *tagSelector { @@ -36,7 +29,7 @@ func (s *tagSelector) Select(tags []*Tag, query string) ([]*Tag, string, error) return s.selectRangeTags(tags, tokens[0], tokens[1]) } - return nil, "", errParse + return nil, "", errFailedQueryParse } func (s *tagSelector) selectSingleTag(tags []*Tag, token string) ([]*Tag, string, error) { @@ -76,7 +69,7 @@ func (*tagSelector) selectBeforeTags(tags []*Tag, token string) ([]*Tag, string, } if len(res) == 0 { - return res, "", errNotFound + return res, "", errNotFoundTag } return res, from, nil @@ -101,7 +94,7 @@ func (*tagSelector) selectAfterTags(tags []*Tag, token string) ([]*Tag, string, } if len(res) == 0 { - return res, "", errNotFound + return res, "", errNotFoundTag } return res, from, nil @@ -133,7 +126,7 @@ func (s *tagSelector) selectRangeTags(tags []*Tag, old string, new string) ([]*T } if len(res) == 0 { - return res, "", errNotFound + return res, "", errNotFoundTag } return res, from, nil diff --git a/utils.go b/utils.go index 01aea857..a67a29ad 100644 --- a/utils.go +++ b/utils.go @@ -1,7 +1,7 @@ package chglog import ( - "errors" + "fmt" "reflect" "strings" "time" @@ -51,7 +51,7 @@ func compare(a interface{}, operator string, b interface{}) (bool, error) { at := reflect.TypeOf(a).String() bt := reflect.TypeOf(a).String() if at != bt { - return false, errors.New("todo: not match type") + return false, fmt.Errorf("\"%s\" and \"%s\" can not be compared", at, bt) } switch at {