mirror of https://github.com/thegeeklab/git-sv.git
180 lines
5.1 KiB
Go
180 lines
5.1 KiB
Go
package main
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/thegeeklab/git-sv/v2/sv"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
//nolint:gochecknoglobals
|
|
var (
|
|
BuildVersion = "devel"
|
|
BuildDate = "00000000"
|
|
)
|
|
|
|
const (
|
|
configFilename = "config.yml"
|
|
configDir = ".gitsv"
|
|
)
|
|
|
|
//go:embed resources/templates/*.tpl
|
|
var defaultTemplatesFS embed.FS
|
|
|
|
func templateFS(filepath string) fs.FS {
|
|
if _, err := os.Stat(filepath); err != nil {
|
|
defaultTemplatesFS, _ := fs.Sub(defaultTemplatesFS, "resources/templates")
|
|
|
|
return defaultTemplatesFS
|
|
}
|
|
|
|
return os.DirFS(filepath)
|
|
}
|
|
|
|
func main() {
|
|
log.SetFlags(0)
|
|
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
log.Fatal("error while retrieving working directory: %w", err)
|
|
}
|
|
|
|
cfg := loadCfg(wd)
|
|
messageProcessor := sv.NewMessageProcessor(cfg.CommitMessage, cfg.Branches)
|
|
git := sv.NewGit(messageProcessor, cfg.Tag)
|
|
semverProcessor := sv.NewSemVerCommitsProcessor(cfg.Versioning, cfg.CommitMessage)
|
|
releasenotesProcessor := sv.NewReleaseNoteProcessor(cfg.ReleaseNotes)
|
|
outputFormatter := sv.NewOutputFormatter(templateFS(filepath.Join(wd, configDir, "templates")))
|
|
|
|
cli.VersionPrinter = func(c *cli.Context) {
|
|
fmt.Printf("%s version=%s date=%s\n", c.App.Name, c.App.Version, BuildDate)
|
|
}
|
|
|
|
app := &cli.App{
|
|
Name: "git-sv",
|
|
Usage: "Semantic version for git.",
|
|
Version: BuildVersion,
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "config",
|
|
Aliases: []string{"cfg"},
|
|
Usage: "cli configuration",
|
|
Subcommands: []*cli.Command{
|
|
{
|
|
Name: "default",
|
|
Usage: "show default config",
|
|
Action: configDefaultHandler(),
|
|
},
|
|
{
|
|
Name: "show",
|
|
Usage: "show current config",
|
|
Action: configShowHandler(cfg),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "current-version",
|
|
Aliases: []string{"cv"},
|
|
Usage: "get last released version from git",
|
|
Action: currentVersionHandler(git),
|
|
},
|
|
{
|
|
Name: "next-version",
|
|
Aliases: []string{"nv"},
|
|
Usage: "generate the next version based on git commit messages",
|
|
Action: nextVersionHandler(git, semverProcessor),
|
|
},
|
|
{
|
|
Name: "commit-log",
|
|
Aliases: []string{"cl"},
|
|
Usage: "list all commit logs according to range as json",
|
|
Description: `The range filter is used based on git log filters, check https://git-scm.com/docs/git-log
|
|
for more info. When flag range is "tag" and start is empty, last tag created will be used instead.
|
|
When flag range is "date", if "end" is YYYY-MM-DD the range will be inclusive.`,
|
|
Action: commitLogHandler(git),
|
|
Flags: commitLogFlags(),
|
|
},
|
|
{
|
|
Name: "commit-notes",
|
|
Aliases: []string{"cn"},
|
|
Usage: "generate a commit notes according to range",
|
|
Description: `The range filter is used based on git log filters, check https://git-scm.com/docs/git-log
|
|
for more info. When flag range is "tag" and start is empty, last tag created will be used instead.
|
|
When flag range is "date", if "end" is YYYY-MM-DD the range will be inclusive.`,
|
|
Action: commitNotesHandler(git, releasenotesProcessor, outputFormatter),
|
|
Flags: commitNotesFlags(),
|
|
},
|
|
{
|
|
Name: "release-notes",
|
|
Aliases: []string{"rn"},
|
|
Usage: "generate release notes",
|
|
Action: releaseNotesHandler(git, semverProcessor, releasenotesProcessor, outputFormatter),
|
|
Flags: releaseNotesFlags(),
|
|
},
|
|
{
|
|
Name: "changelog",
|
|
Aliases: []string{"cgl"},
|
|
Usage: "generate changelog",
|
|
Action: changelogHandler(git, semverProcessor, releasenotesProcessor, outputFormatter),
|
|
Flags: changelogFlags(),
|
|
},
|
|
{
|
|
Name: "tag",
|
|
Aliases: []string{"tg"},
|
|
Usage: "generate tag with version based on git commit messages",
|
|
Action: tagHandler(git, semverProcessor),
|
|
},
|
|
{
|
|
Name: "commit",
|
|
Aliases: []string{"cmt"},
|
|
Usage: "execute git commit with conventional commit message helper",
|
|
Action: commitHandler(cfg, git, messageProcessor),
|
|
Flags: commitFlags(),
|
|
},
|
|
{
|
|
Name: "validate-commit-message",
|
|
Aliases: []string{"vcm"},
|
|
Usage: "use as prepare-commit-message hook to validate and enhance commit message",
|
|
Action: validateCommitMessageHandler(git, messageProcessor),
|
|
Flags: validateCommitMessageFlags(),
|
|
},
|
|
},
|
|
}
|
|
|
|
if apperr := app.Run(os.Args); apperr != nil {
|
|
log.Fatal("ERROR: ", apperr)
|
|
}
|
|
}
|
|
|
|
func loadCfg(wd string) Config {
|
|
cfg := defaultConfig()
|
|
|
|
envCfg := loadEnvConfig()
|
|
if envCfg.Home != "" {
|
|
homeCfgFilepath := filepath.Join(envCfg.Home, configFilename)
|
|
if homeCfg, err := readConfig(homeCfgFilepath); err == nil {
|
|
if merr := merge(&cfg, migrateConfig(homeCfg, homeCfgFilepath)); merr != nil {
|
|
log.Fatal("failed to merge user config, error: ", merr)
|
|
}
|
|
}
|
|
}
|
|
|
|
repoCfgFilepath := filepath.Join(wd, configDir, configFilename)
|
|
if repoCfg, err := readConfig(repoCfgFilepath); err == nil {
|
|
if merr := merge(&cfg, migrateConfig(repoCfg, repoCfgFilepath)); merr != nil {
|
|
log.Fatal("failed to merge repo config, error: ", merr)
|
|
}
|
|
|
|
if len(repoCfg.ReleaseNotes.Headers) > 0 { // mergo is merging maps, headers will be overwritten
|
|
cfg.ReleaseNotes.Headers = repoCfg.ReleaseNotes.Headers
|
|
}
|
|
}
|
|
|
|
return cfg
|
|
}
|