From 2aa7eec88f5c58f29fa5741eb7694b9bb9d080c2 Mon Sep 17 00:00:00 2001 From: Reaper Date: Fri, 10 Jun 2022 17:47:01 +0530 Subject: [PATCH 1/9] setup for the cli redo --- README.md | 2 +- commands/commitlog.go | 7 +++ commands/release.go | 7 +++ go.mod | 3 +- go.sum | 16 ++++-- main.go | 118 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 commands/commitlog.go create mode 100644 commands/release.go diff --git a/README.md b/README.md index 81982de..3ea1e3c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

-

Changelog generator using Commit History

+

commits to changelogs

[![Go Report Card](https://goreportcard.com/badge/github.com/barelyhuman/commitlog)](https://goreportcard.com/report/github.com/barelyhuman/commitlog) diff --git a/commands/commitlog.go b/commands/commitlog.go new file mode 100644 index 0000000..3a3db4a --- /dev/null +++ b/commands/commitlog.go @@ -0,0 +1,7 @@ +package commands + +import "github.com/urfave/cli/v2" + +func Commitlog(c *cli.Context) (err error) { + return +} diff --git a/commands/release.go b/commands/release.go new file mode 100644 index 0000000..7a4bebf --- /dev/null +++ b/commands/release.go @@ -0,0 +1,7 @@ +package commands + +import "github.com/urfave/cli/v2" + +func Release(c *cli.Context) (err error) { + return +} diff --git a/go.mod b/go.mod index 82e1fe9..f81b481 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,12 @@ module github.com/barelyhuman/commitlog -go 1.13 +go 1.16 require ( github.com/AlecAivazis/survey/v2 v2.2.8 github.com/fatih/color v1.12.0 github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-git/v5 v5.2.0 + github.com/urfave/cli/v2 v2.8.1 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/go.sum b/go.sum index c15ba1c..80ecf88 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0= github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= @@ -8,6 +9,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -16,7 +19,6 @@ github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -64,14 +66,20 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4= +github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -91,8 +99,9 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -101,5 +110,6 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/main.go b/main.go index a074bcf..79d75d8 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,121 @@ -// SPDX-License-Identifier: MIT - package main import ( - "github.com/barelyhuman/commitlog/cmd" + _ "embed" + "fmt" + "log" + "os" + + "github.com/barelyhuman/commitlog/commands" + "github.com/urfave/cli/v2" ) +//go:embed .commitlog.release +var version string + func main() { - cmd.Init() + app := &cli.App{ + Name: "commitlog", + Usage: "commits to changelogs", + Action: func(c *cli.Context) error { + fmt.Println( + "[commitlog] we no longer support direct invocation, please use the subcommand `generate` to generate a log or `release` to manage your .commitlog.release", + ) + + return nil + }, + Commands: []*cli.Command{ + { + Name: "generate", + Aliases: []string{"g"}, + Usage: "commits to changelogs", + Action: func(c *cli.Context) error { + return commands.Commitlog(c) + }, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "promo", + Usage: "add promo text to the end of output", + }, + &cli.StringFlag{ + Name: "out", + Usage: "path to the output `FILE`", + }, + &cli.BoolFlag{ + Name: "stdio", + Usage: "print to the stdout", + }, + &cli.StringFlag{ + Name: "start", + Usage: "`START` reference for the commit to include commits from," + + "This is inclusive of the given commit reference", + }, + &cli.StringFlag{ + Name: "end", + Usage: "`END` reference for the commit to stop including commits at." + + "This is exclusive of the given commit reference", + }, + }, + }, + { + Name: "release", + Aliases: []string{"r"}, + Usage: "manage .commitlog.release version", + Action: func(c *cli.Context) error { + return commands.Release(c) + }, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "init", + Usage: "initialise commitlog release", + }, + &cli.BoolFlag{ + Name: "pre-release", + Usage: "create a pre-release version. will default to patch increment unless" + + "specified and not already a pre-release", + }, + &cli.StringFlag{ + Name: "pre-release-tag", + Value: "beta", + Usage: "create a pre-release version", + }, + &cli.BoolFlag{ + Name: "major", + Usage: "create a major version", + }, + &cli.BoolFlag{ + Name: "minor", + Usage: "create a minor version", + }, + &cli.BoolFlag{ + Name: "patch", + Usage: "create a patch version", + }, + &cli.BoolFlag{ + Name: "commit", + Value: false, + Usage: "if true will create a commit, of the changed version", + }, + &cli.BoolFlag{ + Name: "tag", + Value: false, + Usage: "if true will create a tag, with the given version", + }, + }, + }, + }, + } + + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print only the version", + } + + app.Version = version + + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } } From e3445f430b8deaf474339b78100d1f69cfb1c1ac Mon Sep 17 00:00:00 2001 From: Reaper Date: Sat, 11 Jun 2022 17:49:49 +0530 Subject: [PATCH 2/9] feat: generator subcommand implementation implement the base set of functionality for the generator command TODO: should improve the naming of the internal structs --- .gitignore | 3 +- commands/commitlog.go | 67 +++++++++- lib/commits.go | 51 +++++++ main.go | 23 +++- pkg/generator.go | 304 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 441 insertions(+), 7 deletions(-) create mode 100644 lib/commits.go create mode 100644 pkg/generator.go diff --git a/.gitignore b/.gitignore index 8fc5d91..d6f3ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ CHANGELOG.md ./commitlog .DS_Store -dist \ No newline at end of file +dist +commitlog diff --git a/commands/commitlog.go b/commands/commitlog.go index 3a3db4a..b87b6a5 100644 --- a/commands/commitlog.go +++ b/commands/commitlog.go @@ -1,7 +1,70 @@ package commands -import "github.com/urfave/cli/v2" +import ( + "github.com/barelyhuman/commitlog/pkg" + "github.com/urfave/cli/v2" +) func Commitlog(c *cli.Context) (err error) { - return + path := c.String("path") + addPromo := c.Bool("promo") + out := c.String("out") + stdio := c.Bool("stdio") + startRef := c.String("start") + endRef := c.String("end") + categories := c.String("categories") + + gOptions := []pkg.GeneratorConfigMod{} + + if addPromo { + gOptions = append(gOptions, + pkg.WithPromo(), + ) + } + + // either write to a file or to the stdio with true by default + if len(out) > 0 { + gOptions = append(gOptions, + pkg.WithOutputToFile(out), + ) + } else if stdio { + gOptions = append(gOptions, + pkg.WithOutputToStdio(), + ) + } + + if len(startRef) > 0 { + gOptions = append(gOptions, + pkg.WithStartReference(startRef), + ) + } + + if len(endRef) > 0 { + gOptions = append(gOptions, + pkg.WithEndReference(endRef), + ) + } + + if len(categories) > 0 { + gOptions = append(gOptions, + pkg.WithCategories(categories), + ) + } + + generator := pkg.CreateGenerator(path, + gOptions...) + + err = generator.ReadCommmits() + + if err != nil { + return err + } + + err = generator.Classify() + + if err != nil { + return err + } + + return generator.Generate() } diff --git a/lib/commits.go b/lib/commits.go new file mode 100644 index 0000000..b71616c --- /dev/null +++ b/lib/commits.go @@ -0,0 +1,51 @@ +package lib + +import ( + "log" + "strings" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" +) + +func IsHashATag(currentRepository *git.Repository, hash plumbing.Hash) bool { + isTag := false + tags, _ := currentRepository.Tags() + tags.ForEach(func(tagRef *plumbing.Reference) error { + revHash, err := currentRepository.ResolveRevision(plumbing.Revision(tagRef.Name())) + if err != nil { + return err + } + if *revHash == hash { + isTag = true + } + return nil + }) + return isTag +} + +func GetCommitFromString(repo *git.Repository, commitString string) *object.Commit { + if commitString == "" { + return nil + } + + hash, err := repo.ResolveRevision(plumbing.Revision(commitString)) + if err != nil { + log.Fatal("Unable to get Repo head:", err) + } + + commitRef, err := repo.CommitObject(*hash) + if err != nil { + log.Fatal("Unable to get resolve commit:", err) + } + return commitRef +} + +func CommitToLog(c *object.Commit) string { + var commitMsg strings.Builder + commitMsg.WriteString(c.Hash.String()) + commitMsg.WriteString(" ") + commitMsg.WriteString(strings.Split(c.Message, "\n")[0]) + return commitMsg.String() +} diff --git a/main.go b/main.go index 79d75d8..67437d0 100644 --- a/main.go +++ b/main.go @@ -33,25 +33,40 @@ func main() { return commands.Commitlog(c) }, Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "path", + Value: ".", + Aliases: []string{"p"}, + Usage: "root with the '.git' folder `PATH`", + }, &cli.BoolFlag{ Name: "promo", Usage: "add promo text to the end of output", }, &cli.StringFlag{ - Name: "out", - Usage: "path to the output `FILE`", + Name: "out", + Aliases: []string{"o"}, + Usage: "path to the output `FILE`", }, &cli.BoolFlag{ Name: "stdio", + Value: true, Usage: "print to the stdout", }, &cli.StringFlag{ - Name: "start", + Name: "categories", + Value: "", + Usage: "categories to use, includes all commits by default. any text you add here will be used to create categories out of the commits", + }, + &cli.StringFlag{ + Name: "start", + Aliases: []string{"s"}, Usage: "`START` reference for the commit to include commits from," + "This is inclusive of the given commit reference", }, &cli.StringFlag{ - Name: "end", + Name: "end", + Aliases: []string{"e"}, Usage: "`END` reference for the commit to stop including commits at." + "This is exclusive of the given commit reference", }, diff --git a/pkg/generator.go b/pkg/generator.go new file mode 100644 index 0000000..b0358b3 --- /dev/null +++ b/pkg/generator.go @@ -0,0 +1,304 @@ +package pkg + +import ( + "fmt" + "io" + "log" + "os" + "regexp" + "strings" + + "github.com/barelyhuman/commitlog/lib" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" +) + +type commitClassification struct { + key string + commits []string +} + +type Generator struct { + repo *git.Repository + workingDirectorPath string + startRef string + endRef string + addPromo bool + categories []string + output struct { + stdio bool + file bool + filePath string + } + classifiedCommits []commitClassification + inMarkdown string + commitToProcess []*object.Commit +} + +type GeneratorConfigMod func(*Generator) + +func (g *Generator) openRepo() { + if g.repo != nil { + return + } + + r, err := git.PlainOpen(g.workingDirectorPath) + if err != nil { + log.Fatal("Error opening Repository: ", err) + } + g.repo = r +} + +func (g *Generator) readCommitsInTags() (err error) { + // make sure the repo is open + g.openRepo() + + var commits []*object.Commit + + var latestTagCommit *object.Commit + var previousTagCommit *object.Commit + + commitsIter, err := g.repo.Log(&git.LogOptions{}) + if err != nil { + err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) + return + } + defer commitsIter.Close() + + // loop through the commits to get the + // most recent tagged commit and the 2nd most recent + // tagged commit + for { + c, err := commitsIter.Next() + + if err == io.EOF { + break + } + + isTag := lib.IsHashATag(g.repo, c.Hash) + if isTag { + if latestTagCommit == nil { + latestTagCommit = c + } else if previousTagCommit == nil { + previousTagCommit = c + break + } + } + } + + commitsIter, err = g.repo.Log(&git.LogOptions{From: latestTagCommit.Hash}) + + if err != nil { + err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) + return + } + defer commitsIter.Close() + + for { + c, err := commitsIter.Next() + + if err == io.EOF { + break + } + + // do not include the last matching commit + if previousTagCommit != nil && c.Hash == previousTagCommit.Hash { + break + } + + commits = append(commits, c) + } + + // this will either have commits between 2 tags or all commits if no tags exist + g.commitToProcess = commits + + return + +} + +func (g *Generator) readCommitsInRange() (err error) { + // make sure the repo is open + g.openRepo() + + var commits []*object.Commit + var commitsIter object.CommitIter + + startHash := lib.GetCommitFromString(g.repo, g.startRef) + endHash := lib.GetCommitFromString(g.repo, g.endRef) + + if startHash != nil { + commitsIter, err = g.repo.Log(&git.LogOptions{From: startHash.Hash}) + } else { + commitsIter, err = g.repo.Log(&git.LogOptions{}) + } + + if err != nil { + err = fmt.Errorf("[commitlog] Failed to get commits from given hash %v", err) + return + } + + for { + c, err := commitsIter.Next() + + if err == io.EOF { + break + } + + if endHash != nil && c.Hash == endHash.Hash { + break + } + + commits = append(commits, c) + } + + g.commitToProcess = commits + + return + +} + +// ReadCommmits will try to collect commits in the given range +// or default to current tag to the previous tag or current commit to +// recent tag, in the same order of priority +func (g *Generator) ReadCommmits() (err error) { + // make sure the repo is open + g.openRepo() + + if len(g.startRef) > 0 || len(g.endRef) > 0 { + g.readCommitsInRange() + } else { + g.readCommitsInTags() + } + + return +} + +func (g *Generator) Classify() (err error) { + // write the classification using the existing commits + if len(g.categories) == 0 { + allCommits := []string{} + + for _, commit := range g.commitToProcess { + allCommits = append(allCommits, lib.CommitToLog(commit)) + } + + g.classifiedCommits = []commitClassification{ + { + key: "All Changes", + commits: allCommits, + }, + } + + return + } + + for _, catg := range g.categories { + rgx, err := regexp.Compile(catg) + if err != nil { + break + } + + catgCommits := []string{} + + for _, commit := range g.commitToProcess { + if !rgx.Match([]byte(commit.Message)) { + continue + } + + catgCommits = append(catgCommits, lib.CommitToLog(commit)) + } + + g.classifiedCommits = append(g.classifiedCommits, commitClassification{ + key: catg, + commits: catgCommits, + }) + } + + return + +} + +func (g *Generator) Generate() (err error) { + + var inMardown strings.Builder + + for _, class := range g.classifiedCommits { + + // title + inMardown.Write([]byte("##")) + inMardown.Write([]byte(" ")) + inMardown.Write([]byte(class.key)) + + inMardown.Write([]byte("\n")) + + // each commit with 2 returns to separate the long description one's + for _, commitMsg := range class.commits { + inMardown.Write([]byte(commitMsg)) + inMardown.Write([]byte("\n\n")) + } + + } + + if g.output.stdio { + fmt.Println(inMardown.String()) + } + + if g.output.file { + err = os.WriteFile(g.output.filePath, []byte(inMardown.String()), os.ModePerm) + if err != nil { + return + } + } + + return +} + +func CreateGenerator(path string, mods ...GeneratorConfigMod) *Generator { + generator := &Generator{ + workingDirectorPath: path, + } + + for _, mod := range mods { + mod(generator) + } + + return generator +} + +func WithPromo() GeneratorConfigMod { + return func(g *Generator) { + g.addPromo = true + } +} + +func WithOutputToFile(filePath string) GeneratorConfigMod { + return func(g *Generator) { + g.output.file = true + g.output.filePath = filePath + } +} + +func WithOutputToStdio() GeneratorConfigMod { + return func(g *Generator) { + g.output.stdio = true + } +} + +func WithStartReference(startRef string) GeneratorConfigMod { + return func(g *Generator) { + g.startRef = startRef + } +} + +func WithEndReference(endRef string) GeneratorConfigMod { + return func(g *Generator) { + g.endRef = endRef + } +} + +func WithCategories(categories string) GeneratorConfigMod { + return func(g *Generator) { + parts := strings.Split(categories, ",") + g.categories = parts + } +} From 7ca3d6f9d8221659b2f612ae683b10df77b0c8bd Mon Sep 17 00:00:00 2001 From: Reaper Date: Sat, 11 Jun 2022 17:58:40 +0530 Subject: [PATCH 3/9] chore: remove fluff from older versions --- cmd/cmd.go | 35 ---- cmd/commitlog/commitlog.go | 48 ----- cmd/release/release.go | 365 ------------------------------------- log/gitutils.go | 70 ------- log/log.go | 258 -------------------------- log/log_test.go | 176 ------------------ log/tag_test.go | 150 --------------- logcategory.go | 120 ------------ 8 files changed, 1222 deletions(-) delete mode 100644 cmd/cmd.go delete mode 100644 cmd/commitlog/commitlog.go delete mode 100644 cmd/release/release.go delete mode 100644 log/gitutils.go delete mode 100644 log/log.go delete mode 100644 log/log_test.go delete mode 100644 log/tag_test.go delete mode 100644 logcategory.go diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index f3355cf..0000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,35 +0,0 @@ -package cmd - -import ( - "os" - - commitlogCmd "github.com/barelyhuman/commitlog/cmd/commitlog" - releaseCmd "github.com/barelyhuman/commitlog/cmd/release" -) - -// Init - initializes the commands and also handles the classification -func Init() { - - // Install the needed commands from the cmd package - releaseCmd.Install() - commitlogCmd.Install() - - // Classify which command to run, also pass the arguments to the command to parse - if len(os.Args) > 1 { - switch os.Args[1] { - case "release": - { - releaseCmd.Run(os.Args[2:]) - return - } - case "log": - { - commitlogCmd.Run(os.Args[2:]) - return - } - } - } - - // Default Command, parse all flags - commitlogCmd.Run(os.Args[1:]) -} diff --git a/cmd/commitlog/commitlog.go b/cmd/commitlog/commitlog.go deleted file mode 100644 index 2ae44ce..0000000 --- a/cmd/commitlog/commitlog.go +++ /dev/null @@ -1,48 +0,0 @@ -package commitlog - -import ( - "flag" - "fmt" - "log" - - clog "github.com/barelyhuman/commitlog/log" -) - -var clogCmd *flag.FlagSet -var repoPath *string -var startCommit *string -var endCommit *string -var inclusionFlags *string -var skipClassification *bool -var addPromotional *bool - -// Install - add flags and other options -func Install() { - clogCmd = flag.NewFlagSet("commitlog", flag.ExitOnError) - repoPath = clogCmd.String("p", ".", "path to the repository, points to the current working directory by default") - startCommit = clogCmd.String("s", "", "commit hash string / revision (ex. HEAD, HEAD^, HEAD~2) \n to start collecting commit messages from") - endCommit = clogCmd.String("e", "", "commit hash string / revision (ex. HEAD, HEAD^, HEAD~2) \n to stop collecting commit message at") - inclusionFlags = clogCmd.String("i", clog.SupportedKeys, "commit types to be includes") - skipClassification = clogCmd.Bool("skip", false, "if enabled will skip trying to classify and just give a list of changes") - addPromotional = clogCmd.Bool("promo", false, "if enabled will add a \"generated by\" promotional tag to the changelog ") -} - -// Run - execute the command -func Run(args []string) { - - err := clogCmd.Parse(args) - - if err != nil { - log.Fatalln(err) - } - - currentRepository := clog.OpenRepository(*repoPath) - - changelog, clogErr := clog.CommitLog(currentRepository, *startCommit, *endCommit, *inclusionFlags, *skipClassification, *addPromotional) - - if clogErr.Err != nil { - log.Fatal(clogErr.Message, clogErr.Err) - } - - fmt.Println(changelog) -} diff --git a/cmd/release/release.go b/cmd/release/release.go deleted file mode 100644 index 978ccab..0000000 --- a/cmd/release/release.go +++ /dev/null @@ -1,365 +0,0 @@ -package release - -import ( - "flag" - "fmt" - "io/fs" - "os" - "strconv" - "strings" - - clog "github.com/barelyhuman/commitlog/log" - "github.com/fatih/color" - "github.com/go-git/go-git/v5" - - survey "github.com/AlecAivazis/survey/v2" -) - -var ( - releaseCmd *flag.FlagSet - major *bool - minor *bool - patch *bool - beta *bool - betaSuffix *string -) - -const configFileName = ".commitlog.release" - -var semverPrompt = &survey.Select{ - Message: "Choose a semver version (choose none for prerelease/beta increments):", - Options: []string{"major", "minor", "patch", "none"}, - Default: "none", -} - -var betaPrompt = &survey.Confirm{ - Message: "Is it a beta release?", -} - -var betaSuffixPrompt = &survey.Input{ - Message: "Enter the exiting beta suffix (if any) (eg: beta or dev or canary) :", - Default: "", -} - -var confirmCreation = &survey.Confirm{ - Message: "Do you want me to create a commit for the new version?:", -} - -type Config struct { - version *TagVersion -} - -// TagVersion - struct holding the broken down tag -type TagVersion struct { - major int64 - minor int64 - patch int64 - beta bool - betaSuffix string - betaVersion int64 -} - -// Install - add flags and other options -func Install() { - releaseCmd = flag.NewFlagSet("release", flag.ExitOnError) - major = releaseCmd.Bool("major", false, "If release is a *major* one, will increment the x.0.0 ") - minor = releaseCmd.Bool("minor", false, "If release is a *minor* one, will increment the 0.x.0 ") - patch = releaseCmd.Bool("patch", false, "If release is a *patch*, will increment the 0.0.x ") - beta = releaseCmd.Bool("beta", false, "If the release is a beta/prerelease") - betaSuffix = releaseCmd.String("beta-suffix", "", "If the release is a beta, to add/increment tag with `-beta.x` or mentioned string") -} - -func bail(err error) { - if err != nil { - fail(err.Error()) - panic(1) - } -} - -func bullet(msg string) { - color.New(color.FgWhite).Add(color.Bold).Println(msg) -} - -func fail(msg string) { - color.New(color.FgRed).Add(color.Bold).Println(msg) -} - -func success(msg string) { - color.New(color.FgGreen).Add(color.Bold).Println(msg) -} - -func dim(msg string) { - color.White(msg) -} - -// Run - execute the command -func Run(args []string) { - - err := releaseCmd.Parse(args) - - bail(err) - - isInitialised, err := checkReleaseInit() - bail(err) - - if !isInitialised { - bullet("Initializing Commitlog Release") - err := initialiseRelease() - bail(err) - success("Created, .commitlog.release") - dim("Please, modify the file to match the current latest version or leave it as is if starting with a new project") - } - - config, err := readConfigFile() - bail(err) - - askQuestions(args) - - err = createRelease(config, *major, *minor, *patch, *beta, *betaSuffix) - - bail(err) -} - -// checkReleaseInit - check if release was already initialised in the particular folder, if not, it'll return false -func checkReleaseInit() (bool, error) { - files, err := os.ReadDir(".") - if err != nil { - return false, err - } - - hasConfigFile := false - - for _, file := range files { - if file.Name() == configFileName { - hasConfigFile = true - } - } - - return hasConfigFile, nil -} - -// initialiseRelease - create the .commitlog.release file in the current folder -// TODO: need to add a question before doing so -func initialiseRelease() error { - err := os.WriteFile(configFileName, []byte("0.0.0"), os.ModePerm) - return err -} - -// readConfigFile - read the file and parse it as a config, limited to version details for now -func readConfigFile() (Config, error) { - config := Config{} - dataInBytes, err := os.ReadFile(configFileName) - if err != nil { - return config, err - } - - asString := string(dataInBytes) - - success("Current Version:") - bullet(asString) - - version, _ := breakTag(asString) - - config.version = version - - return config, nil -} - -// createRelease - create a release based on the read config and given parameters -func createRelease(config Config, incMajor bool, incMinor bool, incPatch bool, incBeta bool, betaSuffixString string) error { - updatedVersion := TagVersion{ - major: config.version.major, - minor: config.version.minor, - patch: config.version.patch, - beta: incBeta, - betaSuffix: betaSuffixString, - betaVersion: config.version.betaVersion, - } - - resetBeta := false - - if incMajor { - updatedVersion.major++ - updatedVersion.minor = 0 - updatedVersion.patch = 0 - resetBeta = true - } - - if incMinor { - updatedVersion.minor++ - updatedVersion.patch = 0 - resetBeta = true - } - - if incPatch { - updatedVersion.patch++ - resetBeta = true - } - - updatedVersionString := fmt.Sprintf("v%v.%v.%v", updatedVersion.major, updatedVersion.minor, updatedVersion.patch) - - if updatedVersion.beta { - if resetBeta { - updatedVersion.betaVersion = 0 - } else { - updatedVersion.betaVersion++ - } - - var sb strings.Builder - - if len(updatedVersion.betaSuffix) > 1 { - sb.WriteString(updatedVersionString + fmt.Sprintf("-%v.", updatedVersion.betaSuffix)) - } else { - sb.WriteString(updatedVersionString + "-") - } - sb.WriteString(fmt.Sprintf("%v", updatedVersion.betaVersion)) - updatedVersionString = sb.String() - } - - success("New Version") - bullet(updatedVersionString) - - var confirmed bool - - survey.AskOne(confirmCreation, &confirmed) - - if !confirmed { - fail("✖ Cancelled") - return nil - } - - err := writeUpdatedVersion(updatedVersionString) - if err != nil { - return err - } - - success("✔ Updated Version") - - return nil -} - -func writeUpdatedVersion(versionString string) error { - err := os.WriteFile(configFileName, []byte(versionString), fs.ModePerm) - if err != nil { - return err - } - - err = createCommit(versionString) - return err -} - -func createCommit(versionString string) error { - repo := clog.OpenRepository(".") - - wt, err := repo.Worktree() - if err != nil { - return err - } - - _, err = wt.Add(configFileName) - if err != nil { - return err - } - - commit, err := wt.Commit(versionString, &git.CommitOptions{}) - if err != nil { - return err - } - - _, err = repo.CreateTag(versionString, commit, &git.CreateTagOptions{ - Message: versionString, - }) - - return err -} - -// askQuestions - Check semver and beta if no args were supplied -func askQuestions(args []string) error { - var semver string - - if len(args) < 1 { - err := survey.AskOne(semverPrompt, &semver) - - if err != nil { - return err - } - - err = survey.AskOne(betaPrompt, beta) - - if err != nil { - return err - } - - if *beta { - err = survey.AskOne(betaSuffixPrompt, betaSuffix) - if err != nil { - return err - } - } - - switch semver { - case "major": - { - *major = true - break - } - case "minor": - { - *minor = true - break - } - case "patch": - { - *patch = true - break - } - } - } - - return nil -} - -// breakTag - break the given semver version string into proper version values, does support breaking semver pre-release strings -func breakTag(tagString string) (*TagVersion, bool) { - hasV := false - version := &TagVersion{} - tagSplits := strings.Split(tagString, ".") - - majorStringSplit := strings.Split(tagSplits[0], "") - - if len(majorStringSplit) > 1 { - hasV = true - major, err := strconv.ParseInt(majorStringSplit[1], 10, 32) - bail(err) - version.major = major - } else { - major, err := strconv.ParseInt(majorStringSplit[0], 10, 32) - bail(err) - version.major = major - } - - minor, err := strconv.ParseInt(tagSplits[1], 10, 32) - bail(err) - version.minor = minor - - if len(tagSplits) > 3 { - version.beta = true - betaV, err := strconv.ParseInt(tagSplits[3], 10, 32) - bail(err) - version.betaVersion = betaV - } else { - version.betaVersion = -1 - } - - patchStringSplit := strings.Split(tagSplits[2], "-") - - patch, err := strconv.ParseInt(patchStringSplit[0], 10, 32) - bail(err) - version.patch = patch - - if len(patchStringSplit) > 1 { - version.betaSuffix = patchStringSplit[1] - } - - return version, hasV -} diff --git a/log/gitutils.go b/log/gitutils.go deleted file mode 100644 index 0981e78..0000000 --- a/log/gitutils.go +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT - -package commitlog - -import ( - "log" - "strings" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/object" -) - -func IsHashATag(currentRepository *git.Repository, hash plumbing.Hash) bool { - isTag := false - tags, _ := currentRepository.Tags() - tags.ForEach(func(tagRef *plumbing.Reference) error { - revHash, err := currentRepository.ResolveRevision(plumbing.Revision(tagRef.Name())) - if err != nil { - return err - } - if *revHash == hash { - isTag = true - } - return nil - }) - return isTag -} - -// normalizeCommit - reduces the commit message to the first line and ignore the description text of the commit -func normalizeCommit(commitMessage string, key string) string { - var message string - for i, msg := range strings.Split(commitMessage, "\n") { - if i == 0 { - message = msg - break - } - } - - removedPrefix := strings.TrimPrefix(strings.TrimSuffix(message, "\n"), key) - return strings.TrimSpace(strings.TrimSuffix(removedPrefix, "\n")) -} - -// OpenRepository - open the git repository and return repository reference -func OpenRepository(path string) *git.Repository { - r, err := git.PlainOpen(path) - if err != nil { - log.Fatal("Error opening Repository: ", err) - } - - return r -} - -// GetCommitFromString - get commit from hash string -func GetCommitFromString(commitString string, repo *git.Repository) *object.Commit { - if commitString == "" { - return nil - } - - hash, err := repo.ResolveRevision(plumbing.Revision(commitString)) - if err != nil { - log.Fatal("Unable to get Repo head:", err) - } - - commitRef, err := repo.CommitObject(*hash) - if err != nil { - log.Fatal("Unable to get resolve commit:", err) - } - return commitRef -} diff --git a/log/log.go b/log/log.go deleted file mode 100644 index 0061b27..0000000 --- a/log/log.go +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: MIT - -package commitlog - -import ( - "bytes" - "fmt" - "regexp" - "strings" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/object" -) - -// SupportedKeys - keys that are supported by the package -const SupportedKeys = "ci|refactor|docs|fix|feat|test|chore|other" - -// ErrMessage - simple interface around error with a custom message -type ErrMessage struct { - Message string - Err error -} - -type commitTypeInclusions [][]byte - -// logContainer - Container of log strings -type logContainer struct { - include bool - commits []string -} - -// logsByCategory - Type to hold logs by each's category -// to be left as ALLCAPS to be considered as symbols instead of selectors -type logsByCategory struct { - CI logContainer - FIX logContainer - REFACTOR logContainer - FEATURE logContainer - DOCS logContainer - CHORE logContainer - TEST logContainer - OTHER logContainer - UNCLASSIFIED logContainer -} - -// Setup - Initialize all Log Containers -func (logs logsByCategory) Setup() { - logs.CI.include = true - logs.FIX.include = true - logs.REFACTOR.include = true - logs.FEATURE.include = true - logs.DOCS.include = true - logs.CHORE.include = true - logs.TEST.include = true - logs.OTHER.include = true - logs.UNCLASSIFIED.include = true -} - -// printLog - loops through the collected logs to write them to string builder -func (container logContainer) printLog(out *strings.Builder, title string, skipped bool) { - if !container.include { - return - } - if len(container.commits) > 0 { - if !skipped { - out.WriteString(fmt.Sprintf("\n\n## %s \n", title)) - } - for _, item := range container.commits { - out.WriteString(item + " \n") - } - } -} - -// ToMarkdown - Generate markdown output for the collected commits -func (logs *logsByCategory) ToMarkdown(skipped bool) string { - var markdownString strings.Builder - - if !skipped { - logs.FEATURE.printLog(&markdownString, "Features", skipped) - logs.FIX.printLog(&markdownString, "Fixes", skipped) - logs.REFACTOR.printLog(&markdownString, "Performance", skipped) - logs.CI.printLog(&markdownString, "CI", skipped) - logs.DOCS.printLog(&markdownString, "Docs", skipped) - logs.CHORE.printLog(&markdownString, "Chores", skipped) - logs.TEST.printLog(&markdownString, "Tests", skipped) - logs.OTHER.printLog(&markdownString, "Other Changes", skipped) - } else { - logs.UNCLASSIFIED.include = true - logs.UNCLASSIFIED.printLog(&markdownString, "Unclassified Changes", skipped) - } - - return markdownString.String() -} - -// AddCommit - Add a commit to the needed logContainer based on skip and include flag -func (logs *logsByCategory) AddCommit(key, commitHash string, skip bool) { - addCommitToContainer := logs.findContainerByKey(key) - if !addCommitToContainer.canAddToContainer(skip) { - addCommitToContainer = &logs.UNCLASSIFIED - } - if addCommitToContainer != nil { - addCommitToContainer.commits = append(addCommitToContainer.commits, commitHash) - } -} - -func (logs *logsByCategory) findContainerByKey(key string) *logContainer { - switch key { - case "ci": - return &logs.CI - case "fix": - return &logs.FIX - case "refactor": - return &logs.REFACTOR - case "feat", "feature": - return &logs.FEATURE - case "docs": - return &logs.DOCS - case "test": - return &logs.TEST - case "chore": - return &logs.CHORE - default: - return &logs.OTHER - } -} - -func (container *logContainer) canAddToContainer(skip bool) bool { - if container.include && !skip { - return true - } else if skip && container.include { - return false - } - return true -} - -// CommitLog - Generate commit log -func CommitLog(currentRepository *git.Repository, startCommitString string, endCommitString string, inclusionFlags string, skipClassification bool, addPromotional bool) (string, ErrMessage) { - baseCommitReference, err := currentRepository.Head() - var startHash, endHash *object.Commit - var cIter object.CommitIter - - if err != nil { - return "", ErrMessage{"Unable to get repository HEAD, are you sure you are in a git repository? Error:", err} - } - - startHash = GetCommitFromString(startCommitString, currentRepository) - endHash = GetCommitFromString(endCommitString, currentRepository) - isHeadTag := false - - if startHash != nil { - cIter, err = currentRepository.Log(&git.LogOptions{From: startHash.Hash}) - } else { - if IsHashATag(currentRepository, baseCommitReference.Hash()) { - isHeadTag = true - } - cIter, err = currentRepository.Log(&git.LogOptions{From: baseCommitReference.Hash()}) - } - - if err != nil { - return "", ErrMessage{"Unable to get repository commits:", err} - } - - var commits []*object.Commit - - var latestTag *object.Commit - var previousTag *object.Commit - tagAssignment := 0 - - err = cIter.ForEach(func(c *object.Commit) error { - commits = append(commits, c) - if isHeadTag && tagAssignment == 0 && latestTag == nil && c.Hash == baseCommitReference.Hash() { - latestTag = c - tagAssignment += 1 - - } else if IsHashATag(currentRepository, c.Hash) { - if latestTag == nil && tagAssignment == 0 { - latestTag = c - tagAssignment += 1 - } - if previousTag == nil && tagAssignment == 1 { - previousTag = c - tagAssignment += 1 - } - } - return nil - }) - - if err != nil { - return "", ErrMessage{"Error getting commits : ", err} - } - - var inclusions commitTypeInclusions - inclusions = append(inclusions, bytes.SplitN([]byte(inclusionFlags), []byte("|"), -1)...) - inclusions = append(inclusions, bytes.SplitN([]byte(inclusionFlags), []byte(","), -1)...) - logContainer := logsByCategory{} - - logContainer.Setup() - - logContainer.CI.include = inclusions.checkInclusion("ci") - logContainer.FIX.include = inclusions.checkInclusion("fix") - logContainer.REFACTOR.include = inclusions.checkInclusion("refactor") - logContainer.FEATURE.include = inclusions.checkInclusion("feat") - logContainer.DOCS.include = inclusions.checkInclusion("docs") - logContainer.CHORE.include = inclusions.checkInclusion("chore") - logContainer.TEST.include = inclusions.checkInclusion("test") - logContainer.OTHER.include = inclusions.checkInclusion("other") - - for _, c := range commits { - key, scopedKey := findKeyInCommit(SupportedKeys, c.Message) - key = strings.SplitN(strings.TrimSpace(key), ":", 2)[0] - normalizedHash := c.Hash.String() + " - " + normalizeCommit(c.Message, scopedKey) - - if endHash == nil && previousTag != nil && previousTag.Hash == c.Hash { - break - } else if endHash != nil && c.Hash == endHash.Hash { - break - } - - logContainer.AddCommit(key, normalizedHash, skipClassification) - - } - - changeLogText := logContainer.ToMarkdown(skipClassification) + "\n" - - if addPromotional { - changeLogText += "generated by [commitlog](https://github.com/commitlog)" - } - - return changeLogText, ErrMessage{} -} - -func (inclusions *commitTypeInclusions) checkInclusion(flagToCheck string) bool { - if inclusions != nil { - for _, flag := range *inclusions { - if string(flag) == flagToCheck { - return true - } - } - } - return false -} - -func findKeyInCommit(key string, commitMessage string) (string, string) { - re := regexp.MustCompile(`^(` + key + `)[:]|^((` + key + `)\((\w+[, /\\]*)+\)[:])`) - keyMatches := re.FindAllStringSubmatch(commitMessage, -1) - if len(keyMatches) == 0 { - return "", "" - } - - scopedKey := keyMatches[0][0] - scopelessKey := keyMatches[0][3] - - if scopelessKey == "" { - scopelessKey = keyMatches[0][1] - } - - return scopelessKey, scopedKey -} diff --git a/log/log_test.go b/log/log_test.go deleted file mode 100644 index 6a200ff..0000000 --- a/log/log_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package commitlog - -import ( - "log" - "strings" - "testing" - "time" - - "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/object" - "github.com/go-git/go-git/v5/storage/memory" -) - -var testCommits []string = []string{ - "fix: fix commit", - "feat: feat commit", - "docs: doc update commit", - "chore: chore commit", - "other commit", -} - -var expectedCommits []string - -func bail(err error) { - if err != nil { - log.Panic(err) - } -} - -func setup() *git.Repository { - var fs = memfs.New() - repo, _ := git.Init(memory.NewStorage(), fs) - wt, err := repo.Worktree() - bail(err) - - for _, testCommitMsg := range testCommits { - commit, err := wt.Commit(testCommitMsg, &git.CommitOptions{ - Author: &object.Signature{ - Name: "Reaper", - Email: "ahoy@barelyhuman.dev", - When: time.Now(), - }, - }) - bail(err) - expectedCommits = append(expectedCommits, commit.String()) - } - - return repo -} - -var repo *git.Repository = setup() - -func TestCommitLogDefault(t *testing.T) { - - log, _ := CommitLog(repo, "", "", SupportedKeys, false, false) - if log == "" { - t.Fail() - } - - for _, commit := range expectedCommits { - if !strings.Contains(log, commit) { - t.Fail() - } - } - - t.Log(log) - -} - -func TestCommitLogSkipped(t *testing.T) { - - log, _ := CommitLog(repo, "", "", SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - for _, commit := range expectedCommits { - // Shouldn't contain classification headings - if strings.Contains(log, "##") { - t.Fail() - } - - if !strings.Contains(log, commit) { - t.Fail() - } - } - - t.Log(log) -} - -func TestCommitLogInclusions(t *testing.T) { - - // include only feature commits - log, _ := CommitLog(repo, "", "", "feat", true, false) - if log == "" { - t.Fail() - } - - ignoredHeadings := []string{ - "## Fixes", - "## Performance", - "## CI", - "## Docs", - "## Chores", - "## Tests", - "## Other Changes", - } - - for _, heading := range ignoredHeadings { - if strings.Contains(log, heading) { - t.Fail() - } - } - - t.Log(log) -} - -func TestCommitLogStartHash(t *testing.T) { - - expectedCommitsLen := len(expectedCommits) - startCommitHash := expectedCommits[expectedCommitsLen-2] - lastCommit := expectedCommits[expectedCommitsLen-1] - acceptedCommitHashes := expectedCommits[0 : expectedCommitsLen-1] - - t.Log("Commits: ", expectedCommits) - t.Log("Start At:", startCommitHash) - - log, _ := CommitLog(repo, startCommitHash, "", SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - // should have all commits except the last one - if strings.Contains(log, lastCommit) { - t.Fail() - } - - for _, commitHash := range acceptedCommitHashes { - if !strings.Contains(log, commitHash) { - t.Log("Failed at:", commitHash) - t.Fail() - } - } - - t.Log("\n", log) -} - -func TestCommitLogEndHash(t *testing.T) { - - endCommitHash := expectedCommits[1] - firstCommit := expectedCommits[0] - acceptedCommitHashes := expectedCommits[2:] - - t.Log("Commits: ", expectedCommits) - t.Log("End At:", endCommitHash) - - log, _ := CommitLog(repo, "", endCommitHash, SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - // should have all commits except the first one - if strings.Contains(log, firstCommit) { - t.Fail() - } - - for _, commitHash := range acceptedCommitHashes { - if !strings.Contains(log, commitHash) { - t.Log("Failed at:", commitHash) - t.Fail() - } - } - - t.Log("\n", log) -} diff --git a/log/tag_test.go b/log/tag_test.go deleted file mode 100644 index 1f2be66..0000000 --- a/log/tag_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package commitlog - -import ( - "strings" - "testing" - "time" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/object" -) - -func getTagOptions(message string) *git.CreateTagOptions { - return &git.CreateTagOptions{ - Message: message, - Tagger: &object.Signature{ - Name: "Test", - Email: "test@reaper.im", - When: time.Now(), - }, - } - -} - -func TestCommitLogSingleTag(t *testing.T) { - secondCommit := expectedCommits[1] - acceptedCommits := expectedCommits[2:] - - t.Log("Commits:", expectedCommits) - t.Log("Tagged:", secondCommit) - - hash, err := repo.ResolveRevision(plumbing.Revision(secondCommit)) - bail(err) - - _, err = repo.CreateTag("0.0.0", *hash, getTagOptions("0.0.0")) - bail(err) - - log, _ := CommitLog(repo, "", "", SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - if strings.Contains(log, expectedCommits[0]) { - t.Fail() - } - - for _, commit := range acceptedCommits { - if !strings.Contains(log, commit) { - t.Fail() - } - } - - t.Log(log) - - // clean-up - bail(repo.DeleteTag("0.0.0")) - -} - -// Test with 2 tags, one on the second commit and one on the 2nd last commit, -// should only have the last commit in the log -func TestCommitLogDualTag(t *testing.T) { - secondCommit := expectedCommits[1] - secondLastCommit := expectedCommits[len(expectedCommits)-2] - acceptedCommit := expectedCommits[len(expectedCommits)-1] - - t.Log("Commits:", expectedCommits) - t.Log("Tagged:", secondCommit, secondLastCommit) - - secondHash, err := repo.ResolveRevision(plumbing.Revision(secondCommit)) - bail(err) - - secondLastHash, err := repo.ResolveRevision(plumbing.Revision(secondLastCommit)) - bail(err) - - _, err = repo.CreateTag("0.0.0", *secondHash, getTagOptions("0.0.0")) - bail(err) - - _, err = repo.CreateTag("0.0.1", *secondLastHash, getTagOptions("0.0.1")) - bail(err) - - log, _ := CommitLog(repo, "", "", SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - for _, commit := range expectedCommits { - if commit == acceptedCommit { - if !strings.Contains(log, acceptedCommit) { - t.Fail() - } - } else { - if strings.Contains(log, commit) { - t.Fail() - } - } - - } - - t.Log(log) - - // clean-up - bail(repo.DeleteTag("0.0.0")) - bail(repo.DeleteTag("0.0.1")) -} - -// Test with 2 tags, one on the second commit and one on the last commit, -// should give all commits till the 1st tag -func TestCommitLogHeadTag(t *testing.T) { - secondCommit := expectedCommits[1] - lastCommit := expectedCommits[len(expectedCommits)-1] - - t.Log("Commits:", expectedCommits) - t.Log("Tagged:", secondCommit, lastCommit) - - secondHash, err := repo.ResolveRevision(plumbing.Revision(secondCommit)) - bail(err) - - lastHash, err := repo.ResolveRevision(plumbing.Revision(lastCommit)) - bail(err) - - _, err = repo.CreateTag("0.0.0", *secondHash, getTagOptions("0.0.0")) - bail(err) - - _, err = repo.CreateTag("0.0.1", *lastHash, getTagOptions("0.0.1")) - bail(err) - - log, _ := CommitLog(repo, "", "", SupportedKeys, true, false) - if log == "" { - t.Fail() - } - - for index, commit := range expectedCommits { - if index <= 1 { - if strings.Contains(log, commit) { - t.Fail() - } - } - if index > 1 && !strings.Contains(log, commit) { - t.Fail() - } - - } - - t.Log(log) - - // clean-up - bail(repo.DeleteTag("0.0.0")) - bail(repo.DeleteTag("0.0.1")) -} diff --git a/logcategory.go b/logcategory.go deleted file mode 100644 index eb96716..0000000 --- a/logcategory.go +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: MIT - -package main - -import ( - "fmt" - "strings" -) - -// logContainer - Container of log strings -type logContainer struct { - include bool - commits []string -} - -// logsByCategory - Type to hold logs by each's category -// to be left as ALLCAPS to be considered as symbols instead of selectors -type logsByCategory struct { - CI logContainer - FIX logContainer - REFACTOR logContainer - FEATURE logContainer - DOCS logContainer - CHORE logContainer - TEST logContainer - OTHER logContainer - UNCLASSIFIED logContainer -} - -// Setup - Initialize all Log Containers -func (logs logsByCategory) Setup() { - logs.CI.include = true - logs.FIX.include = true - logs.REFACTOR.include = true - logs.FEATURE.include = true - logs.DOCS.include = true - logs.CHORE.include = true - logs.TEST.include = true - logs.OTHER.include = true - logs.UNCLASSIFIED.include = true -} - -// printLog - loops through the collected logs to write them to string builder -func (container logContainer) printLog(out *strings.Builder, title string, skipped bool) { - if !container.include { - return - } - if len(container.commits) > 0 { - if !skipped { - out.WriteString(fmt.Sprintf("\n\n## %s \n", title)) - } - for _, item := range container.commits { - out.WriteString(item + "\n") - } - } -} - -// ToMarkdown - Generate markdown output for the collected commits -func (logs *logsByCategory) ToMarkdown(skipped bool) string { - var markdownString strings.Builder - - markdownString.WriteString("# Changelog \n") - - if !skipped { - logs.FEATURE.printLog(&markdownString, "Features", skipped) - logs.FIX.printLog(&markdownString, "Fixes", skipped) - logs.REFACTOR.printLog(&markdownString, "Performance", skipped) - logs.CI.printLog(&markdownString, "CI", skipped) - logs.DOCS.printLog(&markdownString, "Docs", skipped) - logs.CHORE.printLog(&markdownString, "Chores", skipped) - logs.TEST.printLog(&markdownString, "Tests", skipped) - logs.OTHER.printLog(&markdownString, "Other Changes", skipped) - } else { - logs.UNCLASSIFIED.include = true - logs.UNCLASSIFIED.printLog(&markdownString, "Unclassified Changes", skipped) - } - - return markdownString.String() -} - -// AddCommit - Add a commit to the needed logContainer based on skip and include flag -func (logs *logsByCategory) AddCommit(key, commitHash string, skip bool) { - addCommitToContainer := logs.findContainerByKey(key) - if !addCommitToContainer.canAddToContainer(skip) { - addCommitToContainer = &logs.UNCLASSIFIED - } - if addCommitToContainer != nil { - addCommitToContainer.commits = append(addCommitToContainer.commits, commitHash) - } -} - -func (logs *logsByCategory) findContainerByKey(key string) *logContainer { - switch key { - case "ci": - return &logs.CI - case "fix": - return &logs.FIX - case "refactor": - return &logs.REFACTOR - case "feat", "feature": - return &logs.FEATURE - case "docs": - return &logs.DOCS - case "test": - return &logs.TEST - case "chore": - return &logs.CHORE - default: - return &logs.OTHER - } -} - -func (container *logContainer) canAddToContainer(skip bool) bool { - if container.include && !skip { - return true - } else if skip && container.include { - return false - } - return true -} From c004158333e1b8d31eefba813571560534f35410 Mon Sep 17 00:00:00 2001 From: Reaper Date: Fri, 24 Jun 2022 11:46:40 +0530 Subject: [PATCH 4/9] feat: releaser base maj,min,patch setup --- commands/release.go | 55 ++++++++++++++- go.mod | 4 +- go.sum | 34 +++------- main.go | 2 +- pkg/generator.go | 50 ++++++++------ pkg/releaser.go | 160 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 252 insertions(+), 53 deletions(-) create mode 100644 pkg/releaser.go diff --git a/commands/release.go b/commands/release.go index 7a4bebf..41968cb 100644 --- a/commands/release.go +++ b/commands/release.go @@ -1,7 +1,58 @@ package commands -import "github.com/urfave/cli/v2" +import ( + "fmt" + "os" + + "github.com/barelyhuman/commitlog/pkg" + "github.com/urfave/cli/v2" +) func Release(c *cli.Context) (err error) { - return + + _, err = os.ReadFile(".commitlog.release") + + if os.IsNotExist(err) { + err = fmt.Errorf("couldn't find the release file, please run the `--init` flag first") + return + } + + fileData, err := os.ReadFile(".commitlog.release") + + if err != nil { + err = fmt.Errorf("error reading the version file: %v", err) + return err + } + + versionString := string(fileData) + + releaserOpts := []pkg.ReleaserMod{} + + if c.Bool("major") { + releaserOpts = append(releaserOpts, pkg.WithMajorIncrement(), pkg.WithMinorReset(), pkg.WithPatchReset()) + } + + if c.Bool("minor") { + releaserOpts = append(releaserOpts, pkg.WithMinorIncrement(), pkg.WithPatchReset()) + } + + if c.Bool("patch") { + releaserOpts = append(releaserOpts, pkg.WithPatchIncrement()) + } + + releaser, err := pkg.CreateNewReleaser(versionString, releaserOpts...) + + if err != nil { + return err + } + + // TODO: + // add commit + // add tagging + // add push + // methods to the `releaser` + + err = os.WriteFile(".commitlog.release", []byte(releaser.String()), os.ModePerm) + + return err } diff --git a/go.mod b/go.mod index f81b481..c6abd65 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,8 @@ module github.com/barelyhuman/commitlog go 1.16 require ( - github.com/AlecAivazis/survey/v2 v2.2.8 - github.com/fatih/color v1.12.0 - github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-git/v5 v5.2.0 github.com/urfave/cli/v2 v2.8.1 + golang.org/x/mod v0.5.1 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/go.sum b/go.sum index 80ecf88..516600b 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,4 @@ -github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0= -github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= -github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -17,8 +13,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -32,32 +26,18 @@ github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2Jg github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= -github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= -github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -71,7 +51,6 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4= @@ -82,19 +61,19 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRT github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -103,6 +82,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= diff --git a/main.go b/main.go index 67437d0..568420e 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( "github.com/urfave/cli/v2" ) -//go:embed .commitlog.release +// go:embed .commitlog.release var version string func main() { diff --git a/pkg/generator.go b/pkg/generator.go index b0358b3..26c49da 100644 --- a/pkg/generator.go +++ b/pkg/generator.go @@ -13,26 +13,28 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" ) -type commitClassification struct { +// commitsByCategory is a collection of commits by a given key +// the _key_ can be `all-changes` or a dynamic key / pattern defined +// by the user +type commitsByCategory struct { key string commits []string } type Generator struct { - repo *git.Repository - workingDirectorPath string - startRef string - endRef string - addPromo bool - categories []string - output struct { + repo *git.Repository + dirPath string + startRef string + endRef string + addPromo bool + categories []string + output struct { stdio bool file bool filePath string } - classifiedCommits []commitClassification - inMarkdown string - commitToProcess []*object.Commit + classifiedCommits []commitsByCategory + rawCommits []*object.Commit } type GeneratorConfigMod func(*Generator) @@ -42,7 +44,7 @@ func (g *Generator) openRepo() { return } - r, err := git.PlainOpen(g.workingDirectorPath) + r, err := git.PlainOpen(g.dirPath) if err != nil { log.Fatal("Error opening Repository: ", err) } @@ -110,7 +112,7 @@ func (g *Generator) readCommitsInTags() (err error) { } // this will either have commits between 2 tags or all commits if no tags exist - g.commitToProcess = commits + g.rawCommits = commits return @@ -151,7 +153,7 @@ func (g *Generator) readCommitsInRange() (err error) { commits = append(commits, c) } - g.commitToProcess = commits + g.rawCommits = commits return @@ -165,9 +167,15 @@ func (g *Generator) ReadCommmits() (err error) { g.openRepo() if len(g.startRef) > 0 || len(g.endRef) > 0 { - g.readCommitsInRange() + err = g.readCommitsInRange() + if err != nil { + return + } } else { - g.readCommitsInTags() + err = g.readCommitsInTags() + if err != nil { + return + } } return @@ -178,11 +186,11 @@ func (g *Generator) Classify() (err error) { if len(g.categories) == 0 { allCommits := []string{} - for _, commit := range g.commitToProcess { + for _, commit := range g.rawCommits { allCommits = append(allCommits, lib.CommitToLog(commit)) } - g.classifiedCommits = []commitClassification{ + g.classifiedCommits = []commitsByCategory{ { key: "All Changes", commits: allCommits, @@ -200,7 +208,7 @@ func (g *Generator) Classify() (err error) { catgCommits := []string{} - for _, commit := range g.commitToProcess { + for _, commit := range g.rawCommits { if !rgx.Match([]byte(commit.Message)) { continue } @@ -208,7 +216,7 @@ func (g *Generator) Classify() (err error) { catgCommits = append(catgCommits, lib.CommitToLog(commit)) } - g.classifiedCommits = append(g.classifiedCommits, commitClassification{ + g.classifiedCommits = append(g.classifiedCommits, commitsByCategory{ key: catg, commits: catgCommits, }) @@ -255,7 +263,7 @@ func (g *Generator) Generate() (err error) { func CreateGenerator(path string, mods ...GeneratorConfigMod) *Generator { generator := &Generator{ - workingDirectorPath: path, + dirPath: path, } for _, mod := range mods { diff --git a/pkg/releaser.go b/pkg/releaser.go new file mode 100644 index 0000000..e53ad6d --- /dev/null +++ b/pkg/releaser.go @@ -0,0 +1,160 @@ +package pkg + +import ( + "fmt" + "strconv" + "strings" + + "golang.org/x/mod/semver" +) + +type version struct { + major int + minor int + patch int + preString string +} + +type Releaser struct { + raw string + v version + next version +} + +func (r *Releaser) HasPrerelease() bool { + return len(r.v.preString) > 0 +} + +func (r *Releaser) String() (s string) { + var b strings.Builder + + b.Write([]byte("v")) + + b.WriteString(strconv.Itoa(r.next.major)) + b.WriteString(".") + b.WriteString(strconv.Itoa(r.next.minor)) + b.WriteString(".") + b.WriteString(strconv.Itoa(r.next.patch)) + + if len(r.next.preString) > 0 { + b.Write([]byte("-")) + b.Write([]byte(r.next.preString)) + } + + s = b.String() + + return +} + +type ReleaserMod func(*Releaser) + +func CreateNewReleaser(vString string, mods ...ReleaserMod) (r *Releaser, err error) { + + if !semver.IsValid(vString) { + err = fmt.Errorf("invalid version string") + return + } + + r = &Releaser{} + r.raw = vString + + simplifiedV := semver.Canonical(vString) + + vParts := strings.Split(simplifiedV, ".") + + r.v.patch, err = strconv.Atoi(vParts[2]) + if err != nil { + return + } + + r.v.minor, err = strconv.Atoi(vParts[1]) + if err != nil { + return + } + + majorStr := strings.Replace(vParts[0], "v", "", -1) + r.v.major, err = strconv.Atoi(majorStr) + if err != nil { + return + } + + r.v.preString = semver.Prerelease(vString) + + r.next.major = r.v.major + r.next.minor = r.v.minor + r.next.patch = r.v.patch + r.next.preString = r.v.preString + + for _, mod := range mods { + mod(r) + } + + return +} + +func WithPrerelease(pre string) ReleaserMod { + return func(r *Releaser) { + r.next.preString = pre + } +} + +func WithPrereleaseIncrement() ReleaserMod { + return func(r *Releaser) { + preParts := strings.Split(r.v.preString, ".") + prePointer, _ := strconv.Atoi(preParts[1]) + prePointer += 1 + preParts[1] = strconv.Itoa(prePointer) + r.next.preString = strings.Join(preParts[:], ".") + } +} + +func WithMajorIncrement() ReleaserMod { + return func(r *Releaser) { + r.next.major += 1 + } +} + +func WithMinorIncrement() ReleaserMod { + return func(r *Releaser) { + r.next.minor += 1 + } +} + +func WithPatchIncrement() ReleaserMod { + return func(r *Releaser) { + r.next.patch += 1 + } +} + +func WithMajorReset() ReleaserMod { + return func(r *Releaser) { + r.next.major = 0 + } +} + +func WithMinorReset() ReleaserMod { + return func(r *Releaser) { + r.next.minor = 0 + } +} + +func WithPatchReset() ReleaserMod { + return func(r *Releaser) { + r.next.patch = 0 + } +} + +func WithPrereleaseReset() ReleaserMod { + return func(r *Releaser) { + preParts := strings.Split(r.v.preString, ".") + // reset something like `beta.1` to `beta.0` + preParts[1] = strconv.Itoa(0) + r.next.preString = strings.Join(preParts[:], ".") + } +} + +func WithClearPrerelease() ReleaserMod { + return func(r *Releaser) { + r.next.preString = "" + } +} From 70669cf043a38391a7c5120578d391170e927471 Mon Sep 17 00:00:00 2001 From: Reaper Date: Sat, 25 Jun 2022 19:09:25 +0530 Subject: [PATCH 5/9] add commit and push --- commands/release.go | 50 +++++++++++++++++++++++++++++++++++++++------ main.go | 12 ++++++++--- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/commands/release.go b/commands/release.go index 41968cb..9022100 100644 --- a/commands/release.go +++ b/commands/release.go @@ -5,6 +5,9 @@ import ( "os" "github.com/barelyhuman/commitlog/pkg" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing" "github.com/urfave/cli/v2" ) @@ -46,13 +49,48 @@ func Release(c *cli.Context) (err error) { return err } - // TODO: - // add commit - // add tagging - // add push - // methods to the `releaser` - err = os.WriteFile(".commitlog.release", []byte(releaser.String()), os.ModePerm) + if err != nil { + return + } + + openRepo, err := git.PlainOpen(c.String("path")) + if err != nil { + return err + } + + var commitHash plumbing.Hash + wt, err := openRepo.Worktree() + if err != nil { + return err + } + + if c.Bool("commit") { + wt.Add(".commitlog.release") + commitHash, err = wt.Commit("chore: version"+releaser.String(), &git.CommitOptions{}) + if err != nil { + return err + } + + _, err = openRepo.CreateTag(releaser.String(), commitHash, &git.CreateTagOptions{}) + if err != nil { + err = fmt.Errorf("looks like there was error while creating a tag for the version commit, please try again or create a tag manually: %v", err) + return err + } + } + + if c.Bool("push") { + _, err := wt.Status() + if err != nil { + return err + } + + openRepo.Push(&git.PushOptions{ + RemoteName: "origin", + Progress: os.Stdout, + RefSpecs: []config.RefSpec{config.RefSpec("refs/tags/*:refs/tags/*")}, + }) + } return err } diff --git a/main.go b/main.go index 568420e..0a0aa99 100644 --- a/main.go +++ b/main.go @@ -84,6 +84,12 @@ func main() { Name: "init", Usage: "initialise commitlog release", }, + &cli.StringFlag{ + Name: "path", + Value: ".", + Aliases: []string{"p"}, + Usage: "root with the '.git' folder `PATH`", + }, &cli.BoolFlag{ Name: "pre-release", Usage: "create a pre-release version. will default to patch increment unless" + @@ -109,12 +115,12 @@ func main() { &cli.BoolFlag{ Name: "commit", Value: false, - Usage: "if true will create a commit, of the changed version", + Usage: "if true will create a commit and tag, of the changed version", }, &cli.BoolFlag{ - Name: "tag", + Name: "push", Value: false, - Usage: "if true will create a tag, with the given version", + Usage: "if true will create push the created release commit + tag on origin", }, }, }, From c84ada69afa36578fd990135cfcbbe2672a6c0bb Mon Sep 17 00:00:00 2001 From: Reaper Date: Sat, 25 Jun 2022 20:13:13 +0530 Subject: [PATCH 6/9] chore: use baseurl flag on mudkip --- scripts/generate-docs.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/generate-docs.sh b/scripts/generate-docs.sh index f07ccab..5bbfc4a 100755 --- a/scripts/generate-docs.sh +++ b/scripts/generate-docs.sh @@ -6,9 +6,6 @@ curl -o mudkip.tgz -L https://github.com/barelyhuman/mudkip/releases/latest/down tar -xvzf mudkip.tgz install linux-amd64/mudkip /usr/local/bin -# hack for github pages till mudkip doesn't add baseURL functionality -sed -i s#/#/commitlog/#g ./docs/_sidebar.md - -mudkip --stylesheet="./docs/styles.css" +mudkip --stylesheet="./docs/styles.css" --baseurl='/commitlog/' From 1eb568dd015f9e5f3f702c2679daec264ce30ca6 Mon Sep 17 00:00:00 2001 From: Reaper Date: Sat, 25 Jun 2022 20:40:19 +0530 Subject: [PATCH 7/9] feat: handling for pre increment --- commands/release.go | 4 ++++ main.go | 4 ++-- pkg/releaser.go | 10 ++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/commands/release.go b/commands/release.go index 9022100..8efe9d0 100644 --- a/commands/release.go +++ b/commands/release.go @@ -43,6 +43,10 @@ func Release(c *cli.Context) (err error) { releaserOpts = append(releaserOpts, pkg.WithPatchIncrement()) } + if c.Bool("pre") { + releaserOpts = append(releaserOpts, pkg.WithPrereleaseIncrement()) + } + releaser, err := pkg.CreateNewReleaser(versionString, releaserOpts...) if err != nil { diff --git a/main.go b/main.go index 0a0aa99..0972338 100644 --- a/main.go +++ b/main.go @@ -91,12 +91,12 @@ func main() { Usage: "root with the '.git' folder `PATH`", }, &cli.BoolFlag{ - Name: "pre-release", + Name: "pre", Usage: "create a pre-release version. will default to patch increment unless" + "specified and not already a pre-release", }, &cli.StringFlag{ - Name: "pre-release-tag", + Name: "pre-tag", Value: "beta", Usage: "create a pre-release version", }, diff --git a/pkg/releaser.go b/pkg/releaser.go index e53ad6d..ec32656 100644 --- a/pkg/releaser.go +++ b/pkg/releaser.go @@ -37,7 +37,6 @@ func (r *Releaser) String() (s string) { b.WriteString(strconv.Itoa(r.next.patch)) if len(r.next.preString) > 0 { - b.Write([]byte("-")) b.Write([]byte(r.next.preString)) } @@ -62,7 +61,14 @@ func CreateNewReleaser(vString string, mods ...ReleaserMod) (r *Releaser, err er vParts := strings.Split(simplifiedV, ".") - r.v.patch, err = strconv.Atoi(vParts[2]) + preParts := strings.Split(vParts[2], "-") + + if len(preParts) > 1 { + r.v.patch, err = strconv.Atoi(preParts[0]) + } else { + r.v.patch, err = strconv.Atoi(vParts[2]) + } + if err != nil { return } From 30ff5cd8deb7f3732c6668ac0a328a05784f2fe8 Mon Sep 17 00:00:00 2001 From: Reaper Date: Sun, 26 Jun 2022 14:34:51 +0530 Subject: [PATCH 8/9] feat(releaser): add init and pre-tag handlers will add support for using the init flag and pre-tag flags on the release command also adds a sub feature for the path flag --- .gitignore | 1 + commands/release.go | 61 ++++++++++++++++++++++++++++++++------------- pkg/releaser.go | 39 +++++++++++++++++++++++------ 3 files changed, 76 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index d6f3ffe..b74d987 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ CHANGELOG.md .DS_Store dist commitlog +lab \ No newline at end of file diff --git a/commands/release.go b/commands/release.go index 8efe9d0..b527c76 100644 --- a/commands/release.go +++ b/commands/release.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "os" + "path" "github.com/barelyhuman/commitlog/pkg" "github.com/go-git/go-git/v5" @@ -13,14 +14,29 @@ import ( func Release(c *cli.Context) (err error) { - _, err = os.ReadFile(".commitlog.release") + fileDir := c.String("path") + filePath := path.Join(fileDir, ".commitlog.release") + + if c.Bool("init") { + _, err = os.Stat(filePath) + if os.IsNotExist(err) { + err = nil + os.WriteFile(filePath, []byte("v0.0.0"), os.ModePerm) + fmt.Println("[commitlog] Initialized commitlog release") + } else { + err = fmt.Errorf(".commitlog.release already exists, cannot override") + } + return + } + + _, err = os.Stat(filePath) if os.IsNotExist(err) { err = fmt.Errorf("couldn't find the release file, please run the `--init` flag first") return } - fileData, err := os.ReadFile(".commitlog.release") + fileData, err := os.ReadFile(filePath) if err != nil { err = fmt.Errorf("error reading the version file: %v", err) @@ -29,7 +45,12 @@ func Release(c *cli.Context) (err error) { versionString := string(fileData) - releaserOpts := []pkg.ReleaserMod{} + releaserOpts := []pkg.ReleaserMod{ + // add in the pre-tag, + // will be used only if the pre flag + // is true + pkg.WithPreTag(c.String("pre-tag")), + } if c.Bool("major") { releaserOpts = append(releaserOpts, pkg.WithMajorIncrement(), pkg.WithMinorReset(), pkg.WithPatchReset()) @@ -53,30 +74,36 @@ func Release(c *cli.Context) (err error) { return err } - err = os.WriteFile(".commitlog.release", []byte(releaser.String()), os.ModePerm) + err = os.WriteFile(filePath, []byte(releaser.String()), os.ModePerm) if err != nil { return } - openRepo, err := git.PlainOpen(c.String("path")) - if err != nil { - return err - } + var gitRepo *git.Repository + var toTagHash plumbing.Hash + var repoWt *git.Worktree - var commitHash plumbing.Hash - wt, err := openRepo.Worktree() - if err != nil { - return err + if c.Bool("commit") || c.Bool("push") { + gitRepo, err = git.PlainOpen(c.String("path")) + if err != nil { + return err + } + + repoWt, err = gitRepo.Worktree() + + if err != nil { + return err + } } if c.Bool("commit") { - wt.Add(".commitlog.release") - commitHash, err = wt.Commit("chore: version"+releaser.String(), &git.CommitOptions{}) + repoWt.Add(filePath) + toTagHash, err = repoWt.Commit("chore: version"+releaser.String(), &git.CommitOptions{}) if err != nil { return err } - _, err = openRepo.CreateTag(releaser.String(), commitHash, &git.CreateTagOptions{}) + _, err = gitRepo.CreateTag(releaser.String(), toTagHash, &git.CreateTagOptions{}) if err != nil { err = fmt.Errorf("looks like there was error while creating a tag for the version commit, please try again or create a tag manually: %v", err) return err @@ -84,12 +111,12 @@ func Release(c *cli.Context) (err error) { } if c.Bool("push") { - _, err := wt.Status() + _, err := repoWt.Status() if err != nil { return err } - openRepo.Push(&git.PushOptions{ + gitRepo.Push(&git.PushOptions{ RemoteName: "origin", Progress: os.Stdout, RefSpecs: []config.RefSpec{config.RefSpec("refs/tags/*:refs/tags/*")}, diff --git a/pkg/releaser.go b/pkg/releaser.go index ec32656..faa0521 100644 --- a/pkg/releaser.go +++ b/pkg/releaser.go @@ -16,9 +16,10 @@ type version struct { } type Releaser struct { - raw string - v version - next version + raw string + v version + next version + preTag string } func (r *Releaser) HasPrerelease() bool { @@ -37,6 +38,7 @@ func (r *Releaser) String() (s string) { b.WriteString(strconv.Itoa(r.next.patch)) if len(r.next.preString) > 0 { + b.Write([]byte("-")) b.Write([]byte(r.next.preString)) } @@ -86,6 +88,8 @@ func CreateNewReleaser(vString string, mods ...ReleaserMod) (r *Releaser, err er r.v.preString = semver.Prerelease(vString) + r.preTag = strings.Split(r.v.preString, ".")[0] + r.next.major = r.v.major r.next.minor = r.v.minor r.next.patch = r.v.patch @@ -106,11 +110,24 @@ func WithPrerelease(pre string) ReleaserMod { func WithPrereleaseIncrement() ReleaserMod { return func(r *Releaser) { - preParts := strings.Split(r.v.preString, ".") - prePointer, _ := strconv.Atoi(preParts[1]) - prePointer += 1 - preParts[1] = strconv.Itoa(prePointer) - r.next.preString = strings.Join(preParts[:], ".") + + // if a pre string already exists + if len(r.v.preString) > 0 { + preParts := strings.Split(r.v.preString, ".") + prePointer, _ := strconv.Atoi(preParts[1]) + prePointer += 1 + preParts[1] = strconv.Itoa(prePointer) + preParts[0] = r.preTag + r.next.preString = strings.Join(preParts[:], ".") + return + } + + preToCreate := []string{ + r.preTag, + "0", + } + + r.next.preString = strings.Join(preToCreate[:], ".") } } @@ -164,3 +181,9 @@ func WithClearPrerelease() ReleaserMod { r.next.preString = "" } } + +func WithPreTag(preTag string) ReleaserMod { + return func(r *Releaser) { + r.preTag = preTag + } +} From 8a59c295e4f7da6fbd2cd02e5cd1414deea7a9b6 Mon Sep 17 00:00:00 2001 From: Reaper Date: Sun, 26 Jun 2022 14:36:02 +0530 Subject: [PATCH 9/9] chore: swap debugging logger with stderr printer removes the logger as most of the logical part has been now tested --- main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 0972338..f975fee 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( _ "embed" "fmt" - "log" "os" "github.com/barelyhuman/commitlog/commands" @@ -88,7 +87,8 @@ func main() { Name: "path", Value: ".", Aliases: []string{"p"}, - Usage: "root with the '.git' folder `PATH`", + Usage: "`PATH` to a folder where .commitlog.release exists or is to be created." + + "(note: do not use `--commit` or `--push` if the file isn't in the root)", }, &cli.BoolFlag{ Name: "pre", @@ -137,6 +137,6 @@ func main() { err := app.Run(os.Args) if err != nil { - log.Fatal(err) + fmt.Fprintf(os.Stderr, "[commitlog] %v", err) } }