diff --git a/tools/goctl/api/apigen/gen.go b/tools/goctl/api/apigen/gen.go index 9b2c838215c6..b0022623f1ac 100644 --- a/tools/goctl/api/apigen/gen.go +++ b/tools/goctl/api/apigen/gen.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -17,13 +17,20 @@ import ( //go:embed api.tpl var apiTemplate string -// ApiCommand create api template file -func ApiCommand(c *cli.Context) error { - if c.NumFlags() == 0 { - cli.ShowAppHelpAndExit(c, 1) - } +var ( + // VarStringOutput describes the output. + VarStringOutput string + // VarStringHome describes the goctl home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the git branch. + VarStringBranch string +) - apiFile := c.String("o") +// CreateApiTemplate create api template file +func CreateApiTemplate(_ *cobra.Command, _ []string) error { + apiFile := VarStringOutput if len(apiFile) == 0 { return errors.New("missing -o") } @@ -34,18 +41,15 @@ func ApiCommand(c *cli.Context) error { } defer fp.Close() - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") - if len(remote) > 0 { - repo, _ := util.CloneIntoGitHome(remote, branch) + if len(VarStringRemote) > 0 { + repo, _ := util.CloneIntoGitHome(VarStringRemote, VarStringBranch) if len(repo) > 0 { - home = repo + VarStringHome = repo } } - if len(home) > 0 { - pathx.RegisterGoctlHome(home) + if len(VarStringHome) > 0 { + pathx.RegisterGoctlHome(VarStringHome) } text, err := pathx.LoadTemplate(category, apiTemplateFile, apiTemplate) diff --git a/tools/goctl/api/apigen/template.go b/tools/goctl/api/apigen/template.go index 8237badd84df..a303a01ae37e 100644 --- a/tools/goctl/api/apigen/template.go +++ b/tools/goctl/api/apigen/template.go @@ -3,7 +3,6 @@ package apigen import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -27,7 +26,7 @@ func Clean() error { } // GenTemplates generates api template files. -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/api/cmd.go b/tools/goctl/api/cmd.go new file mode 100644 index 000000000000..76288fc7b93d --- /dev/null +++ b/tools/goctl/api/cmd.go @@ -0,0 +1,176 @@ +package api + +import ( + "github.com/spf13/cobra" + "github.com/zeromicro/go-zero/tools/goctl/api/apigen" + "github.com/zeromicro/go-zero/tools/goctl/api/dartgen" + "github.com/zeromicro/go-zero/tools/goctl/api/docgen" + "github.com/zeromicro/go-zero/tools/goctl/api/format" + "github.com/zeromicro/go-zero/tools/goctl/api/gogen" + "github.com/zeromicro/go-zero/tools/goctl/api/javagen" + "github.com/zeromicro/go-zero/tools/goctl/api/ktgen" + "github.com/zeromicro/go-zero/tools/goctl/api/new" + "github.com/zeromicro/go-zero/tools/goctl/api/tsgen" + "github.com/zeromicro/go-zero/tools/goctl/api/validate" + "github.com/zeromicro/go-zero/tools/goctl/plugin" +) + +var ( + // Cmd describes a api command. + Cmd = &cobra.Command{ + Use: "api", + Short: "Generate api related files", + RunE: apigen.CreateApiTemplate, + } + + dartCmd = &cobra.Command{ + Use: "dart", + Short: "Generate dart files for provided api in api file", + RunE: dartgen.DartCommand, + } + + docCmd = &cobra.Command{ + Use: "doc", + Short: "Generate doc files", + RunE: docgen.DocCommand, + } + + formatCmd = &cobra.Command{ + Use: "format", + Short: "Format api files", + RunE: format.GoFormatApi, + } + + goCmd = &cobra.Command{ + Use: "go", + Short: "Generate go files for provided api in yaml file", + RunE: gogen.GoCommand, + } + + newCmd = &cobra.Command{ + Use: "new", + Short: "Fast create api service", + Example: "goctl api new [options] service-name", + Args: cobra.ExactValidArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return new.CreateServiceCommand(args) + }, + } + + validateCmd = &cobra.Command{ + Use: "validate", + Short: "Validate api file", + RunE: validate.GoValidateApi, + } + + javaCmd = &cobra.Command{ + Use: "java", + Short: "Generate java files for provided api in api file", + RunE: javagen.JavaCommand, + } + + ktCmd = &cobra.Command{ + Use: "kt", + Short: "Generate kotlin code for provided api file", + RunE: ktgen.KtCommand, + } + + pluginCmd = &cobra.Command{ + Use: "plugin", + Short: "Custom file generator", + RunE: plugin.PluginCommand, + } + + tsCmd = &cobra.Command{ + Use: "ts", + Short: "Generate ts files for provided api in api file", + RunE: tsgen.TsCommand, + } +) + +func init() { + Cmd.Flags().StringVar(&apigen.VarStringOutput, "o", "", "Output a sample api file") + Cmd.Flags().StringVar(&apigen.VarStringHome, "home", "", "The goctl home path of the"+ + " template, --home and --remote cannot be set at the same time, if they are, --remote has "+ + "higher priority") + Cmd.Flags().StringVar(&apigen.VarStringRemote, "remote", "", "The remote git repo of the"+ + " template, --home and --remote cannot be set at the same time, if they are, --remote has higher"+ + " priority\n\tThe git repo directory must be consistent with the"+ + " https://github.com/zeromicro/go-zero-template directory structure") + Cmd.Flags().StringVar(&apigen.VarStringBranch, "branch", "master", "The branch of the "+ + "remote repo, it does work with --remote") + + dartCmd.Flags().StringVar(&dartgen.VarStringDir, "dir", "", "The target dir") + dartCmd.Flags().StringVar(&dartgen.VarStringAPI, "api", "", "The api file") + dartCmd.Flags().BoolVar(&dartgen.VarStringLegacy, "legacy", false, "Legacy generator for flutter v1") + dartCmd.Flags().StringVar(&dartgen.VarStringHostname, "hostname", "", "hostname of the server") + + docCmd.Flags().StringVar(&docgen.VarStringDir, "dir", "", "The target dir") + docCmd.Flags().StringVar(&docgen.VarStringOutput, "o", "", "The output markdown directory") + + formatCmd.Flags().StringVar(&format.VarStringDir, "dir", "", "The format target dir") + formatCmd.Flags().BoolVar(&format.VarBoolIgnore, "iu", false, "Ignore update") + formatCmd.Flags().BoolVar(&format.VarBoolUseStdin, "stdin", false, "Use stdin to input api"+ + " doc content, press \"ctrl + d\" to send EOF") + formatCmd.Flags().BoolVar(&format.VarBoolSkipCheckDeclare, "declare", false, "Use to skip check "+ + "api types already declare") + + goCmd.Flags().StringVar(&gogen.VarStringDir, "dir", "", "The target dir") + goCmd.Flags().StringVar(&gogen.VarStringAPI, "api", "", "The api file") + goCmd.Flags().StringVar(&gogen.VarStringHome, "home", "", "The goctl home path of "+ + "the template, --home and --remote cannot be set at the same time, if they are, --remote "+ + "has higher priority") + goCmd.Flags().StringVar(&gogen.VarStringRemote, "remote", "", "The remote git repo "+ + "of the template, --home and --remote cannot be set at the same time, if they are, --remote"+ + " has higher priority\n\tThe git repo directory must be consistent with the "+ + "https://github.com/zeromicro/go-zero-template directory structure") + goCmd.Flags().StringVar(&gogen.VarStringBranch, "branch", "master", "The branch of "+ + "the remote repo, it does work with --remote") + goCmd.Flags().StringVar(&gogen.VarStringStyle, "style", "gozero", "The file naming format,"+ + " see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]") + + javaCmd.Flags().StringVar(&javagen.VarStringDir, "dir", "", "The target dir") + javaCmd.Flags().StringVar(&javagen.VarStringAPI, "api", "", "The api file") + + ktCmd.Flags().StringVar(&ktgen.VarStringDir, "dir", "", "The target dir") + ktCmd.Flags().StringVar(&ktgen.VarStringAPI, "api", "", "The api file") + ktCmd.Flags().StringVar(&ktgen.VarStringPKG, "pkg", "", "Define package name for kotlin file") + + newCmd.Flags().StringVar(&new.VarStringHome, "home", "", "The goctl home path of "+ + "the template, --home and --remote cannot be set at the same time, if they are, --remote "+ + "has higher priority") + newCmd.Flags().StringVar(&new.VarStringRemote, "remote", "", "The remote git repo "+ + "of the template, --home and --remote cannot be set at the same time, if they are, --remote"+ + " has higher priority\n\tThe git repo directory must be consistent with the "+ + "https://github.com/zeromicro/go-zero-template directory structure") + newCmd.Flags().StringVar(&new.VarStringBranch, "branch", "master", "The branch of "+ + "the remote repo, it does work with --remote") + newCmd.Flags().StringVar(&new.VarStringStyle, "style", "gozero", "The file naming format,"+ + " see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]") + + pluginCmd.Flags().StringVarP(&plugin.VarStringPlugin, "plugin", "p", "", "The plugin file") + pluginCmd.Flags().StringVar(&plugin.VarStringDir, "dir", "", "The target dir") + pluginCmd.Flags().StringVar(&plugin.VarStringAPI, "api", "", "The api file") + pluginCmd.Flags().StringVar(&plugin.VarStringStyle, "style", "", + "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + + tsCmd.Flags().StringVar(&tsgen.VarStringDir, "dir", "", "The target dir") + tsCmd.Flags().StringVar(&tsgen.VarStringAPI, "api", "", "The api file") + tsCmd.Flags().StringVar(&tsgen.VarStringWebAPI, "webapi", "", "The web api file path") + tsCmd.Flags().StringVar(&tsgen.VarStringCaller, "caller", "", "The web api caller") + tsCmd.Flags().BoolVar(&tsgen.VarBoolUnWrap, "unwrap", false, "Unwrap the webapi caller for import") + + validateCmd.Flags().StringVar(&validate.VarStringAPI, "api", "", "Validate target api file") + + // Add sub-commands + Cmd.AddCommand(dartCmd) + Cmd.AddCommand(docCmd) + Cmd.AddCommand(formatCmd) + Cmd.AddCommand(goCmd) + Cmd.AddCommand(javaCmd) + Cmd.AddCommand(ktCmd) + Cmd.AddCommand(newCmd) + Cmd.AddCommand(pluginCmd) + Cmd.AddCommand(tsCmd) + Cmd.AddCommand(validateCmd) +} diff --git a/tools/goctl/api/dartgen/gen.go b/tools/goctl/api/dartgen/gen.go index a3fafb42696e..b73e39019d7c 100644 --- a/tools/goctl/api/dartgen/gen.go +++ b/tools/goctl/api/dartgen/gen.go @@ -5,17 +5,28 @@ import ( "fmt" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/tools/goctl/api/parser" ) +var ( + // VarStringDir describes the directory. + VarStringDir string + // VarStringAPI defines the API. + VarStringAPI string + // VarStringLegacy describes whether legacy. + VarStringLegacy bool + // VarStringHostname defines the hostname. + VarStringHostname string +) + // DartCommand create dart network request code -func DartCommand(c *cli.Context) error { - apiFile := c.String("api") - dir := c.String("dir") - isLegacy := c.Bool("legacy") - hostname := c.String("hostname") +func DartCommand(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI + dir := VarStringDir + isLegacy := VarStringLegacy + hostname := VarStringHostname if len(apiFile) == 0 { return errors.New("missing -api") } diff --git a/tools/goctl/api/docgen/gen.go b/tools/goctl/api/docgen/gen.go index fee801d60e07..03179b921e31 100644 --- a/tools/goctl/api/docgen/gen.go +++ b/tools/goctl/api/docgen/gen.go @@ -7,19 +7,26 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) +var ( + // VarStringDir describes a directory. + VarStringDir string + // VarStringOutput describes an output directory. + VarStringOutput string +) + // DocCommand generate Markdown doc file -func DocCommand(c *cli.Context) error { - dir := c.String("dir") +func DocCommand(_ *cobra.Command, _ []string) error { + dir := VarStringDir if len(dir) == 0 { return errors.New("missing -dir") } - outputDir := c.String("o") + outputDir := VarStringOutput if len(outputDir) == 0 { var err error outputDir, err = os.Getwd() diff --git a/tools/goctl/api/format/format.go b/tools/goctl/api/format/format.go index e7283b47829d..97576db3cda5 100644 --- a/tools/goctl/api/format/format.go +++ b/tools/goctl/api/format/format.go @@ -12,7 +12,7 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/errorx" "github.com/zeromicro/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/util" @@ -26,30 +26,37 @@ const ( rightBrace = "}" ) -// GoFormatApi format api file -func GoFormatApi(c *cli.Context) error { - useStdin := c.Bool("stdin") - skipCheckDeclare := c.Bool("declare") - dir := c.String("dir") +var ( + // VarBoolUseStdin describes whether to use stdin or not. + VarBoolUseStdin bool + // VarBoolSkipCheckDeclare describes whether to skip. + VarBoolSkipCheckDeclare bool + // VarStringDir describes the directory. + VarStringDir string + // VarBoolIgnore describes whether to ignore. + VarBoolIgnore bool +) +// GoFormatApi format api file +func GoFormatApi(_ *cobra.Command, _ []string) error { var be errorx.BatchError - if useStdin { - if err := apiFormatReader(os.Stdin, dir, skipCheckDeclare); err != nil { + if VarBoolUseStdin { + if err := apiFormatReader(os.Stdin, VarStringDir, VarBoolSkipCheckDeclare); err != nil { be.Add(err) } } else { - if len(dir) == 0 { + if len(VarStringDir) == 0 { return errors.New("missing -dir") } - _, err := os.Lstat(dir) + _, err := os.Lstat(VarStringDir) if err != nil { - return errors.New(dir + ": No such file or directory") + return errors.New(VarStringDir + ": No such file or directory") } - err = filepath.Walk(dir, func(path string, fi os.FileInfo, errBack error) (err error) { + err = filepath.Walk(VarStringDir, func(path string, fi os.FileInfo, errBack error) (err error) { if strings.HasSuffix(path, ".api") { - if err := ApiFormatByPath(path, skipCheckDeclare); err != nil { + if err := ApiFormatByPath(path, VarBoolSkipCheckDeclare); err != nil { be.Add(util.WrapErr(err, fi.Name())) } } diff --git a/tools/goctl/api/gogen/gen.go b/tools/goctl/api/gogen/gen.go index fa9a31ccd766..02c5186f4e40 100644 --- a/tools/goctl/api/gogen/gen.go +++ b/tools/goctl/api/gogen/gen.go @@ -12,7 +12,7 @@ import ( "time" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/logx" apiformat "github.com/zeromicro/go-zero/tools/goctl/api/format" "github.com/zeromicro/go-zero/tools/goctl/api/parser" @@ -24,16 +24,30 @@ import ( const tmpFile = "%s-%d" -var tmpDir = path.Join(os.TempDir(), "goctl") +var ( + tmpDir = path.Join(os.TempDir(), "goctl") + // VarStringDir describes the directory. + VarStringDir string + // VarStringAPI describes the API. + VarStringAPI string + // VarStringHome describes the go home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the branch. + VarStringBranch string + // VarStringStyle describes the style of output files. + VarStringStyle string +) // GoCommand gen go project files from command line -func GoCommand(c *cli.Context) error { - apiFile := c.String("api") - dir := c.String("dir") - namingStyle := c.String("style") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") +func GoCommand(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI + dir := VarStringDir + namingStyle := VarStringStyle + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := util.CloneIntoGitHome(remote, branch) if len(repo) > 0 { diff --git a/tools/goctl/api/gogen/template.go b/tools/goctl/api/gogen/template.go index 1089298f24cf..580fef4f8b3f 100644 --- a/tools/goctl/api/gogen/template.go +++ b/tools/goctl/api/gogen/template.go @@ -3,7 +3,6 @@ package gogen import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -45,7 +44,7 @@ func Clean() error { } // GenTemplates generates api template files. -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/api/javagen/gen.go b/tools/goctl/api/javagen/gen.go index 2515ededd105..34103b75272e 100644 --- a/tools/goctl/api/javagen/gen.go +++ b/tools/goctl/api/javagen/gen.go @@ -6,16 +6,23 @@ import ( "strings" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) +var ( + // VarStringDir describes a directory. + VarStringDir string + // VarStringAPI describes an API. + VarStringAPI string +) + // JavaCommand generates java code command entrance. -func JavaCommand(c *cli.Context) error { - apiFile := c.String("api") - dir := c.String("dir") +func JavaCommand(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI + dir := VarStringDir if len(apiFile) == 0 { return errors.New("missing -api") } diff --git a/tools/goctl/api/ktgen/cmd.go b/tools/goctl/api/ktgen/cmd.go index fe07dabf1e1b..7a68f9c76c7a 100644 --- a/tools/goctl/api/ktgen/cmd.go +++ b/tools/goctl/api/ktgen/cmd.go @@ -3,21 +3,30 @@ package ktgen import ( "errors" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/api/parser" ) +var ( + // VarStringDir describes a directory. + VarStringDir string + // VarStringAPI describes an API. + VarStringAPI string + // VarStringPKG describes a package. + VarStringPKG string +) + // KtCommand generates kotlin code command entrance -func KtCommand(c *cli.Context) error { - apiFile := c.String("api") +func KtCommand(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI if apiFile == "" { return errors.New("missing -api") } - dir := c.String("dir") + dir := VarStringDir if dir == "" { return errors.New("missing -dir") } - pkg := c.String("pkg") + pkg := VarStringPKG if pkg == "" { return errors.New("missing -pkg") } diff --git a/tools/goctl/api/new/newservice.go b/tools/goctl/api/new/newservice.go index fb872bc7b8c5..707fe3d139f4 100644 --- a/tools/goctl/api/new/newservice.go +++ b/tools/goctl/api/new/newservice.go @@ -8,7 +8,6 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/api/gogen" conf "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/util" @@ -18,18 +17,22 @@ import ( //go:embed api.tpl var apiTemplate string -// CreateServiceCommand fast create service -func CreateServiceCommand(c *cli.Context) error { - if c.NArg() == 0 { - cli.ShowCommandHelpAndExit(c, "new", 1) - } - - args := c.Args() - dirName := args.First() +var ( + // VarStringHome describes the goctl home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the git branch. + VarStringBranch string + // VarStringStyle describes the style of output files. + VarStringStyle string +) - dirStyle := c.String("style") - if len(dirStyle) == 0 { - dirStyle = conf.DefaultFormat +// CreateServiceCommand fast create service +func CreateServiceCommand(args []string) error { + dirName := args[0] + if len(VarStringStyle) == 0 { + VarStringStyle = conf.DefaultFormat } if strings.Contains(dirName, "-") { return errors.New("api new command service name not support strikethrough, because this will used by function name") @@ -55,18 +58,15 @@ func CreateServiceCommand(c *cli.Context) error { defer fp.Close() - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") - if len(remote) > 0 { - repo, _ := util.CloneIntoGitHome(remote, branch) + if len(VarStringRemote) > 0 { + repo, _ := util.CloneIntoGitHome(VarStringRemote, VarStringBranch) if len(repo) > 0 { - home = repo + VarStringHome = repo } } - if len(home) > 0 { - pathx.RegisterGoctlHome(home) + if len(VarStringHome) > 0 { + pathx.RegisterGoctlHome(VarStringHome) } text, err := pathx.LoadTemplate(category, apiTemplateFile, apiTemplate) @@ -82,6 +82,6 @@ func CreateServiceCommand(c *cli.Context) error { return err } - err = gogen.DoGenProject(apiFilePath, abs, dirStyle) + err = gogen.DoGenProject(apiFilePath, abs, VarStringStyle) return err } diff --git a/tools/goctl/api/new/template.go b/tools/goctl/api/new/template.go index eab11cb0798d..f4460fdcd945 100644 --- a/tools/goctl/api/new/template.go +++ b/tools/goctl/api/new/template.go @@ -3,7 +3,6 @@ package new import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -27,7 +26,7 @@ func Clean() error { } // GenTemplates generates api template files. -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/api/tsgen/gen.go b/tools/goctl/api/tsgen/gen.go index 88c021f3f223..c8c0a9d599c1 100644 --- a/tools/goctl/api/tsgen/gen.go +++ b/tools/goctl/api/tsgen/gen.go @@ -5,19 +5,32 @@ import ( "fmt" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) +var ( + // VarStringDir describes a directory. + VarStringDir string + // VarStringAPI describes an API file. + VarStringAPI string + // VarStringWebAPI describes a web API file. + VarStringWebAPI string + // VarStringCaller describes a caller. + VarStringCaller string + // VarBoolUnWrap describes whether wrap or not. + VarBoolUnWrap bool +) + // TsCommand provides the entry to generate typescript codes -func TsCommand(c *cli.Context) error { - apiFile := c.String("api") - dir := c.String("dir") - webAPI := c.String("webapi") - caller := c.String("caller") - unwrapAPI := c.Bool("unwrap") +func TsCommand(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI + dir := VarStringDir + webAPI := VarStringWebAPI + caller := VarStringCaller + unwrapAPI := VarBoolUnWrap if len(apiFile) == 0 { return errors.New("missing -api") } diff --git a/tools/goctl/api/validate/validate.go b/tools/goctl/api/validate/validate.go index ad5d93337f0a..2660e28ef9c0 100644 --- a/tools/goctl/api/validate/validate.go +++ b/tools/goctl/api/validate/validate.go @@ -5,13 +5,16 @@ import ( "fmt" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/api/parser" ) +// VarStringAPI describes an API. +var VarStringAPI string + // GoValidateApi verifies whether the api has a syntax error -func GoValidateApi(c *cli.Context) error { - apiFile := c.String("api") +func GoValidateApi(_ *cobra.Command, _ []string) error { + apiFile := VarStringAPI if len(apiFile) == 0 { return errors.New("missing -api") diff --git a/tools/goctl/bug/bug.go b/tools/goctl/bug/bug.go index a497e29485f6..85e4eb94d701 100644 --- a/tools/goctl/bug/bug.go +++ b/tools/goctl/bug/bug.go @@ -6,7 +6,7 @@ import ( "os/exec" "runtime" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/internal/version" ) @@ -29,7 +29,7 @@ var openCmd = map[string]string{ darwin: darwinOpen, } -func Action(_ *cli.Context) error { +func runE(_ *cobra.Command, _ []string) error { env := getEnv() content := fmt.Sprintf(issueTemplate, version.BuildVersion, env.string()) content = url.QueryEscape(content) diff --git a/tools/goctl/bug/cmd.go b/tools/goctl/bug/cmd.go new file mode 100644 index 000000000000..c259991b3146 --- /dev/null +++ b/tools/goctl/bug/cmd.go @@ -0,0 +1,11 @@ +package bug + +import "github.com/spf13/cobra" + +// Cmd describes a bug command. +var Cmd = &cobra.Command{ + Use: "bug", + Short: "Report a bug", + Args: cobra.NoArgs, + RunE: runE, +} diff --git a/tools/goctl/cmd/root.go b/tools/goctl/cmd/root.go new file mode 100644 index 000000000000..ccbb03532006 --- /dev/null +++ b/tools/goctl/cmd/root.go @@ -0,0 +1,101 @@ +package cmd + +import ( + "fmt" + "os" + "runtime" + "strings" + + "github.com/logrusorgru/aurora" + "github.com/spf13/cobra" + "github.com/zeromicro/go-zero/tools/goctl/api" + "github.com/zeromicro/go-zero/tools/goctl/bug" + "github.com/zeromicro/go-zero/tools/goctl/docker" + "github.com/zeromicro/go-zero/tools/goctl/env" + "github.com/zeromicro/go-zero/tools/goctl/internal/version" + "github.com/zeromicro/go-zero/tools/goctl/kube" + "github.com/zeromicro/go-zero/tools/goctl/migrate" + "github.com/zeromicro/go-zero/tools/goctl/model" + "github.com/zeromicro/go-zero/tools/goctl/rpc" + "github.com/zeromicro/go-zero/tools/goctl/tpl" + "github.com/zeromicro/go-zero/tools/goctl/upgrade" +) + +const ( + codeFailure = 1 + dash = "-" + doubleDash = "--" + assign = "=" +) + +var rootCmd = &cobra.Command{ + Use: "goctl", + Short: "A cli tool to generate go-zero code", + Long: "A cli tool to generate api, zrpc, model code", +} + +// Execute executes the given command +func Execute() { + os.Args = supportGoStdFlag(os.Args) + if err := rootCmd.Execute(); err != nil { + fmt.Println(aurora.Red(err.Error())) + os.Exit(codeFailure) + } +} + +func supportGoStdFlag(args []string) []string { + copyArgs := append([]string(nil), args...) + parentCmd, _, err := rootCmd.Traverse(args[:1]) + if err != nil { // ignore it to let cobra handle the error. + return copyArgs + } + + for idx, arg := range copyArgs[0:] { + parentCmd, _, err = parentCmd.Traverse([]string{arg}) + if err != nil { // ignore it to let cobra handle the error. + break + } + if !strings.HasPrefix(arg, dash) { + continue + } + + flagExpr := strings.TrimPrefix(arg, doubleDash) + flagExpr = strings.TrimPrefix(flagExpr, dash) + flagName, flagValue := flagExpr, "" + assignIndex := strings.Index(flagExpr, assign) + if assignIndex > 0 { + flagName = flagExpr[:assignIndex] + flagValue = flagExpr[assignIndex:] + } + + f := parentCmd.Flag(flagName) + if f == nil { + continue + } + if f.Shorthand == flagName { + continue + } + + goStyleFlag := doubleDash + f.Name + if assignIndex > 0 { + goStyleFlag += flagValue + } + + copyArgs[idx] = goStyleFlag + } + return copyArgs +} + +func init() { + rootCmd.Version = fmt.Sprintf("%s %s/%s", version.BuildVersion, runtime.GOOS, runtime.GOARCH) + rootCmd.AddCommand(api.Cmd) + rootCmd.AddCommand(bug.Cmd) + rootCmd.AddCommand(docker.Cmd) + rootCmd.AddCommand(kube.Cmd) + rootCmd.AddCommand(env.Cmd) + rootCmd.AddCommand(model.Cmd) + rootCmd.AddCommand(migrate.Cmd) + rootCmd.AddCommand(rpc.Cmd) + rootCmd.AddCommand(tpl.Cmd) + rootCmd.AddCommand(upgrade.Cmd) +} diff --git a/tools/goctl/compare/cmd/cmd.go b/tools/goctl/compare/cmd/cmd.go new file mode 100644 index 000000000000..335ee877e99f --- /dev/null +++ b/tools/goctl/compare/cmd/cmd.go @@ -0,0 +1,23 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/zeromicro/go-zero/tools/goctl/compare/testdata" + "github.com/zeromicro/go-zero/tools/goctl/util/console" +) + +var rootCmd = &cobra.Command{ + Use: "compare", + Short: "Compare the goctl commands generated results between urfave and cobra", + Args: cobra.ExactValidArgs(1), + Run: func(cmd *cobra.Command, args []string) { + dir := args[0] + testdata.MustRun(dir) + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + console.Error("%+v", err) + } +} diff --git a/tools/goctl/compare/compare.go b/tools/goctl/compare/compare.go new file mode 100644 index 000000000000..c483d1346253 --- /dev/null +++ b/tools/goctl/compare/compare.go @@ -0,0 +1,11 @@ +package main + +import "github.com/zeromicro/go-zero/tools/goctl/compare/cmd" + +// EXPRIMENTAL: compare goctl generated code results between old and new, it will be removed in the feature. +// TODO: BEFORE RUNNING: export DSN=$datasource, the database must be gozero, and there has no limit for tables. +// TODO: AFTER RUNNING: diff --recursive old_fs new_fs + +func main() { + cmd.Execute() +} diff --git a/tools/goctl/compare/make.sh b/tools/goctl/compare/make.sh new file mode 100644 index 000000000000..7fb3d824ae88 --- /dev/null +++ b/tools/goctl/compare/make.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +wd=`dirname $0` +GOBIN="$GOPATH/bin" +EXE=goctl-compare +go build -o $EXE $wd +mv $EXE $GOBIN diff --git a/tools/goctl/compare/testdata/kotlin.api b/tools/goctl/compare/testdata/kotlin.api new file mode 100644 index 000000000000..6eed57ed369c --- /dev/null +++ b/tools/goctl/compare/testdata/kotlin.api @@ -0,0 +1,17 @@ +syntax = "v1" + +info( + title: "type title here" + desc: "type desc here" + author: "type author here" + email: "type email here" + version: "type version here" +) + +type req{} +type reply{} + +service kotlin-api{ + @handler ping + post /ping +} diff --git a/tools/goctl/compare/testdata/testcase.go b/tools/goctl/compare/testdata/testcase.go new file mode 100644 index 000000000000..772346d76fb5 --- /dev/null +++ b/tools/goctl/compare/testdata/testcase.go @@ -0,0 +1,470 @@ +package testdata + +import _ "embed" + +var ( + //go:embed unformat.api + unformatApi string + //go:embed kotlin.api + kotlinApi string + //go:embed user.sql + userSql string + + list = Files{ + { + IsDir: true, + Path: "version", + Cmd: "goctl --version", + }, + { + IsDir: true, + Path: "api/sample_file/local", + Cmd: "goctl api --o sample.api", + }, + { + IsDir: true, + Path: "api/sample_file/local/assign", + Cmd: "goctl api --o=sample.api", + }, + { + IsDir: true, + Path: "api/sample_file/local/assign/shorthand", + Cmd: "goctl api -o=sample.api", + }, + { + IsDir: true, + Path: "api/sample_file/remote", + Cmd: "goctl api --o sample.api --remote https://github.com/zeromicro/go-zero-template --branch main", + }, + { + IsDir: true, + Path: "api/sample_file/remote/shorthand", + Cmd: "goctl api -o sample.api -remote https://github.com/zeromicro/go-zero-template -branch main", + }, + { + IsDir: true, + Path: "api/sample_file/remote/assign", + Cmd: "goctl api --o=sample.api --remote https://github.com/zeromicro/go-zero-template --branch=main", + }, + { + IsDir: true, + Path: "api/sample_file/remote/assign/shorthand", + Cmd: "goctl api -o=sample.api -remote https://github.com/zeromicro/go-zero-template -branch=main", + }, + { + IsDir: true, + Path: "api/dart/legacy/true", + Cmd: "goctl api --o sample.api && goctl api dart --api sample.api --dir . --hostname 127.0.0.1 --legacy true", + }, + { + IsDir: true, + Path: "api/dart/legacy/true/shorthand", + Cmd: "goctl api -o sample.api && goctl api dart -api sample.api -dir . -hostname 127.0.0.1 -legacy true", + }, + { + IsDir: true, + Path: "api/dart/legacy/true/assign", + Cmd: "goctl api --o=sample.api && goctl api dart --api=sample.api --dir=. --hostname=127.0.0.1 --legacy=true", + }, + { + IsDir: true, + Path: "api/dart/legacy/true/assign/shorthand", + Cmd: "goctl api -o=sample.api && goctl api dart -api=sample.api -dir=. -hostname=127.0.0.1 -legacy=true", + }, + { + IsDir: true, + Path: "api/dart/legacy/false", + Cmd: "goctl api --o sample.api && goctl api dart --api sample.api --dir . --hostname 127.0.0.1 --legacy true", + }, + { + IsDir: true, + Path: "api/dart/legacy/false/shorthand", + Cmd: "goctl api -o sample.api && goctl api dart -api sample.api -dir . -hostname 127.0.0.1 -legacy true", + }, + { + IsDir: true, + Path: "api/dart/legacy/false/assign", + Cmd: "goctl api --o=sample.api && goctl api dart --api=sample.api --dir=. --hostname=127.0.0.1 --legacy=true", + }, + { + IsDir: true, + Path: "api/dart/legacy/false/assign/shorthand", + Cmd: "goctl api -o=sample.api && goctl api dart -api=sample.api -dir=. -hostname=127.0.0.1 -legacy=true", + }, + { + IsDir: true, + Path: "api/doc", + Cmd: "goctl api --o sample.api && goctl api doc --dir . --o .", + }, + { + IsDir: true, + Path: "api/doc/shorthand", + Cmd: "goctl api -o sample.api && goctl api doc -dir . -o .", + }, + { + IsDir: true, + Path: "api/doc/assign", + Cmd: "goctl api --o=sample.api && goctl api doc --dir=. --o=.", + }, + { + IsDir: true, + Path: "api/doc/assign/shorthand", + Cmd: "goctl api -o=sample.api && goctl api doc -dir=. -o=.", + }, + { + Path: "api/format/unformat.api", + Content: unformatApi, + Cmd: "goctl api format --dir . --iu", + }, + { + Path: "api/format/shorthand/unformat.api", + Content: unformatApi, + Cmd: "goctl api format -dir . -iu", + }, + { + Path: "api/format/assign/unformat.api", + Content: unformatApi, + Cmd: "goctl api format --dir=. --iu", + }, + { + Path: "api/format/assign/shorthand/unformat.api", + Content: unformatApi, + Cmd: "goctl api format -dir=. -iu", + }, + { + IsDir: true, + Path: "api/go/style/default", + Cmd: "goctl api --o sample.api && goctl api go --api sample.api --dir .", + }, + { + IsDir: true, + Path: "api/go/style/default/shorthand", + Cmd: "goctl api -o sample.api && goctl api go -api sample.api -dir .", + }, + { + IsDir: true, + Path: "api/go/style/assign/default", + Cmd: "goctl api --o=sample.api && goctl api go --api=sample.api --dir=.", + }, + { + IsDir: true, + Path: "api/go/style/assign/default/shorthand", + Cmd: "goctl api -o=sample.api && goctl api go -api=sample.api -dir=.", + }, + { + IsDir: true, + Path: "api/go/style/goZero", + Cmd: "goctl api --o sample.api && goctl api go --api sample.api --dir . --style goZero", + }, + { + IsDir: true, + Path: "api/go/style/goZero/shorthand", + Cmd: "goctl api -o sample.api && goctl api go -api sample.api -dir . -style goZero", + }, + { + IsDir: true, + Path: "api/go/style/goZero/assign", + Cmd: "goctl api --o=sample.api && goctl api go --api=sample.api --dir=. --style=goZero", + }, + { + IsDir: true, + Path: "api/go/style/goZero/assign/shorthand", + Cmd: "goctl api -o=sample.api && goctl api go -api=sample.api -dir=. -style=goZero", + }, + { + IsDir: true, + Path: "api/java", + Cmd: "goctl api --o sample.api && goctl api java --api sample.api --dir .", + }, + { + IsDir: true, + Path: "api/java/shorthand", + Cmd: "goctl api -o sample.api && goctl api java -api sample.api -dir .", + }, + { + IsDir: true, + Path: "api/java/assign", + Cmd: "goctl api --o=sample.api && goctl api java --api=sample.api --dir=.", + }, + { + IsDir: true, + Path: "api/java/shorthand/assign", + Cmd: "goctl api -o=sample.api && goctl api java -api=sample.api -dir=.", + }, + { + IsDir: true, + Path: "api/new/style/default", + Cmd: "goctl api new greet", + }, + { + IsDir: true, + Path: "api/new/style/goZero", + Cmd: "goctl api new greet --style goZero", + }, + { + IsDir: true, + Path: "api/new/style/goZero/assign", + Cmd: "goctl api new greet --style=goZero", + }, + { + IsDir: true, + Path: "api/new/style/goZero/shorthand", + Cmd: "goctl api new greet -style goZero", + }, + { + IsDir: true, + Path: "api/new/style/goZero/shorthand/assign", + Cmd: "goctl api new greet -style=goZero", + }, + { + IsDir: true, + Path: "api/ts", + Cmd: "goctl api --o sample.api && goctl api ts --api sample.api --dir . --unwrap --webapi .", + }, + { + IsDir: true, + Path: "api/ts/shorthand", + Cmd: "goctl api -o sample.api && goctl api ts -api sample.api -dir . -unwrap -webapi .", + }, + { + IsDir: true, + Path: "api/ts/assign", + Cmd: "goctl api --o=sample.api && goctl api ts --api=sample.api --dir=. --unwrap --webapi=.", + }, + { + IsDir: true, + Path: "api/ts/shorthand/assign", + Cmd: "goctl api -o=sample.api && goctl api ts -api=sample.api -dir=. -unwrap -webapi=.", + }, + { + IsDir: true, + Path: "api/validate", + Cmd: "goctl api --o sample.api && goctl api validate --api sample.api", + }, + { + IsDir: true, + Path: "api/validate/shorthand", + Cmd: "goctl api -o sample.api && goctl api validate -api sample.api", + }, + { + IsDir: true, + Path: "api/validate/assign", + Cmd: "goctl api --o=sample.api && goctl api validate --api=sample.api", + }, + { + IsDir: true, + Path: "api/validate/shorthand/assign", + Cmd: "goctl api -o=sample.api && goctl api validate -api=sample.api", + }, + { + IsDir: true, + Path: "env/show", + Cmd: "goctl env > env.txt", + }, + { + IsDir: true, + Path: "env/check", + Cmd: "goctl env check -f -v", + }, + { + IsDir: true, + Path: "env/install", + Cmd: "goctl env install -v", + }, + { + IsDir: true, + Path: "kube", + Cmd: "goctl kube deploy --image alpine --name foo --namespace foo --o foo.yaml --port 8888", + }, + { + IsDir: true, + Path: "kube/shorthand", + Cmd: "goctl kube deploy -image alpine -name foo -namespace foo -o foo.yaml -port 8888", + }, + { + IsDir: true, + Path: "kube/assign", + Cmd: "goctl kube deploy --image=alpine --name=foo --namespace=foo --o=foo.yaml --port=8888", + }, + { + IsDir: true, + Path: "kube/shorthand/assign", + Cmd: "goctl kube deploy -image=alpine -name=foo -namespace=foo -o=foo.yaml -port=8888", + }, + { + IsDir: true, + Path: "model/mongo/cache", + Cmd: "goctl model mongo --dir . --type user --style goZero -c", + }, + { + IsDir: true, + Path: "model/mongo/cache/shorthand", + Cmd: "goctl model mongo -dir . -type user -style goZero -c", + }, + { + IsDir: true, + Path: "model/mongo/cache/assign", + Cmd: "goctl model mongo --dir=. --type=user --style=goZero -c", + }, + { + IsDir: true, + Path: "model/mongo/cache/shorthand/assign", + Cmd: "goctl model mongo -dir=. -type=user -style=goZero -c", + }, + { + IsDir: true, + Path: "model/mongo/nocache", + Cmd: "goctl model mongo --dir . --type user", + }, + { + IsDir: true, + Path: "model/mongo/nocache/shorthand", + Cmd: "goctl model mongo -dir . -type user", + }, + { + IsDir: true, + Path: "model/mongo/nocache/assign", + Cmd: "goctl model mongo --dir=. --type=user", + }, + { + IsDir: true, + Path: "model/mongo/nocache/shorthand/assign", + Cmd: "goctl model mongo -dir=. -type=user", + }, + { + Content: userSql, + Path: "model/mysql/ddl/user.sql", + Cmd: "goctl model mysql ddl --database user --dir cache --src user.sql -c", + }, + { + Content: userSql, + Path: "model/mysql/ddl/shorthand/user.sql", + Cmd: "goctl model mysql ddl -database user -dir cache -src user.sql -c", + }, + { + Content: userSql, + Path: "model/mysql/ddl/assign/user.sql", + Cmd: "goctl model mysql ddl --database=user --dir=cache --src=user.sql -c", + }, + { + Content: userSql, + Path: "model/mysql/ddl/shorthand/assign/user.sql", + Cmd: "goctl model mysql ddl -database=user -dir=cache -src=user.sql -c", + }, + { + Content: userSql, + Path: "model/mysql/ddl/user.sql", + Cmd: "goctl model mysql ddl --database user --dir nocache --src user.sql", + }, + { + Content: userSql, + Path: "model/mysql/ddl/shorthand/user.sql", + Cmd: "goctl model mysql ddl -database user -dir nocache -src user.sql", + }, + { + Content: userSql, + Path: "model/mysql/ddl/assign/user.sql", + Cmd: "goctl model mysql ddl --database=user --dir=nocache --src=user.sql", + }, + { + Content: userSql, + Path: "model/mysql/ddl/shorthand/assign/user.sql", + Cmd: "goctl model mysql ddl -database=user -dir=nocache -src=user.sql", + }, + { + IsDir: true, + Path: "model/mysql/datasource", + Cmd: `goctl model mysql datasource --url $DSN --dir cache --table "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand", + Cmd: `goctl model mysql datasource -url $DSN -dir cache -table "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand2", + Cmd: `goctl model mysql datasource -url $DSN -dir cache -t "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/assign", + Cmd: `goctl model mysql datasource --url=$DSN --dir=cache --table="*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand/assign", + Cmd: `goctl model mysql datasource -url=$DSN -dir=cache -table="*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand2/assign", + Cmd: `goctl model mysql datasource -url=$DSN -dir=cache -t="*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource", + Cmd: `goctl model mysql datasource --url $DSN --dir nocache --table "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand", + Cmd: `goctl model mysql datasource -url $DSN -dir nocache -table "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand2", + Cmd: `goctl model mysql datasource -url $DSN -dir nocache -t "*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/assign", + Cmd: `goctl model mysql datasource --url=$DSN --dir=nocache --table="*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand/assign", + Cmd: `goctl model mysql datasource -url=$DSN -dir=nocache -table="*" -c`, + }, + { + IsDir: true, + Path: "model/mysql/datasource/shorthand2/assign", + Cmd: `goctl model mysql datasource -url=$DSN -dir=nocache -t="*" -c`, + }, + { + IsDir: true, + Path: "rpc/new", + Cmd: "goctl rpc new greet", + }, + { + IsDir: true, + Path: "rpc/template", + Cmd: "goctl rpc template --o greet.proto", + }, + { + IsDir: true, + Path: "rpc/template/shorthand", + Cmd: "goctl rpc template -o greet.proto", + }, + { + IsDir: true, + Path: "rpc/template/assign", + Cmd: "goctl rpc template --o=greet.proto", + }, + { + IsDir: true, + Path: "rpc/template/shorthand/assign", + Cmd: "goctl rpc template -o=greet.proto", + }, + { + IsDir: true, + Path: "rpc/protoc", + Cmd: "goctl rpc template --o greet.proto && goctl rpc protoc greet.proto --go_out . --go-grpc_out . --zrpc_out .", + }, + { + IsDir: true, + Path: "rpc/protoc/assign", + Cmd: "goctl rpc template --o=greet.proto && goctl rpc protoc greet.proto --go_out=. --go-grpc_out=. --zrpc_out=.", + }, + } +) diff --git a/tools/goctl/compare/testdata/testdata.go b/tools/goctl/compare/testdata/testdata.go new file mode 100644 index 000000000000..b2092641997e --- /dev/null +++ b/tools/goctl/compare/testdata/testdata.go @@ -0,0 +1,120 @@ +package testdata + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/logrusorgru/aurora" + "github.com/zeromicro/go-zero/tools/goctl/util/pathx" +) + +type ( + File struct { + IsDir bool + Path string + AbsolutePath string + Content string + Cmd string + } + + Files []File +) + +func (f File) execute(goctl string) error { + printDir := f.Path + dir := f.AbsolutePath + if !f.IsDir { + printDir = filepath.Dir(printDir) + dir = filepath.Dir(dir) + } + printCommand := strings.ReplaceAll(fmt.Sprintf("cd %s && %s", printDir, f.Cmd), "goctl", filepath.Base(goctl)) + command := strings.ReplaceAll(fmt.Sprintf("cd %s && %s", dir, f.Cmd), "goctl", goctl) + fmt.Println(aurora.BrightGreen(printCommand)) + cmd := exec.Command("sh", "-c", command) + cmd.Env = os.Environ() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func (fs Files) execute(goctl string) error { + for _, f := range fs { + err := f.execute(goctl) + if err != nil { + return err + } + } + return nil +} + +func mustGetTestData(baseDir string) (Files, Files) { + if len(baseDir) == 0 { + dir, err := os.Getwd() + if err != nil { + log.Fatalln(err) + } + baseDir = dir + } + baseDir, err := filepath.Abs(baseDir) + if err != nil { + return nil, nil + } + createFile := func(baseDir string, data File) (File, error) { + fp := filepath.Join(baseDir, data.Path) + dir := filepath.Dir(fp) + if data.IsDir { + dir = fp + } + if err := pathx.MkdirIfNotExist(dir); err != nil { + return data, err + } + data.AbsolutePath = fp + if data.IsDir { + return data, nil + } + + return data, ioutil.WriteFile(fp, []byte(data.Content), os.ModePerm) + } + oldDir := filepath.Join(baseDir, "old_fs") + newDir := filepath.Join(baseDir, "new_fs") + os.RemoveAll(oldDir) + os.RemoveAll(newDir) + var oldFiles, newFiles []File + for _, data := range list { + od, err := createFile(oldDir, data) + if err != nil { + log.Fatalln(err) + } + oldFiles = append(oldFiles, od) + nd, err := createFile(newDir, data) + if err != nil { + log.Fatalln(err) + } + newFiles = append(newFiles, nd) + } + return oldFiles, newFiles +} + +func MustRun(baseDir string) { + oldFiles, newFiles := mustGetTestData(baseDir) + goctlOld, err := exec.LookPath("goctl.old") + must(err) + goctlNew, err := exec.LookPath("goctl") + must(err) + fmt.Println(aurora.BrightBlue("========================goctl.old=======================")) + must(oldFiles.execute(goctlOld)) + fmt.Println() + fmt.Println(aurora.BrightBlue("========================goctl.new=======================")) + must(newFiles.execute(goctlNew)) +} + +func must(err error) { + if err != nil { + log.Fatalln(err) + } +} diff --git a/tools/goctl/compare/testdata/unformat.api b/tools/goctl/compare/testdata/unformat.api new file mode 100644 index 000000000000..debea8e3ea78 --- /dev/null +++ b/tools/goctl/compare/testdata/unformat.api @@ -0,0 +1,3 @@ +syntax = "v1" + +type Foo struct{} diff --git a/tools/goctl/compare/testdata/user.sql b/tools/goctl/compare/testdata/user.sql new file mode 100644 index 000000000000..48531dc30dc3 --- /dev/null +++ b/tools/goctl/compare/testdata/user.sql @@ -0,0 +1,34 @@ +-- 用户表 -- +CREATE TABLE `user` +( + `id` bigint(10) NOT NULL AUTO_INCREMENT, + `user` varchar(50) NOT NULL DEFAULT '' COMMENT '用户', + `name` varchar(255) COLLATE utf8mb4_general_ci NULL COMMENT '用户\t名称', + `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户\n密码', + `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号', + `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公\r开', + `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称', + `type` tinyint(1) COLLATE utf8mb4_general_ci DEFAULT 0 COMMENT '用户类型', + `create_time` timestamp NULL, + `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `name_index` (`name`), + UNIQUE KEY `name_index2` (`name`), + UNIQUE KEY `user_index` (`user`), + UNIQUE KEY `type_index` (`type`), + UNIQUE KEY `mobile_index` (`mobile`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `student` +( + `type` bigint NOT NULL, + `class` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '', + `name` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '', + `age` tinyint DEFAULT NULL, + `score` float(10, 0 +) DEFAULT NULL, + `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`type`) USING BTREE, + UNIQUE KEY `class_name_index` (`class`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; \ No newline at end of file diff --git a/tools/goctl/completion/completion.go b/tools/goctl/completion/completion.go deleted file mode 100644 index 5e29e52e9f16..000000000000 --- a/tools/goctl/completion/completion.go +++ /dev/null @@ -1,77 +0,0 @@ -package completion - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "runtime" - - "github.com/logrusorgru/aurora" - "github.com/urfave/cli" - "github.com/zeromicro/go-zero/tools/goctl/util/pathx" - "github.com/zeromicro/go-zero/tools/goctl/vars" -) - -func Completion(c *cli.Context) error { - goos := runtime.GOOS - if goos == vars.OsWindows { - return fmt.Errorf("%q: only support unix-like OS", goos) - } - - name := c.String("name") - if len(name) == 0 { - name = defaultCompletionFilename - } - if filepath.IsAbs(name) { - return fmt.Errorf("unsupport absolute path: %q", name) - } - - home, err := pathx.GetAutoCompleteHome() - if err != nil { - return err - } - - buffer := bytes.NewBuffer(nil) - zshF := filepath.Join(home, "zsh", defaultCompletionFilename) - err = pathx.MkdirIfNotExist(filepath.Dir(zshF)) - if err != nil { - return err - } - - bashF := filepath.Join(home, "bash", defaultCompletionFilename) - err = pathx.MkdirIfNotExist(filepath.Dir(bashF)) - if err != nil { - return err - } - - flag := magic - err = ioutil.WriteFile(zshF, zsh, os.ModePerm) - if err == nil { - flag |= flagZsh - } - - err = ioutil.WriteFile(bashF, bash, os.ModePerm) - if err == nil { - flag |= flagBash - } - - buffer.WriteString(aurora.BrightGreen("generation auto completion success!\n").String()) - buffer.WriteString(aurora.BrightGreen("executes the following script to setting shell:\n").String()) - switch flag { - case magic | flagZsh: - buffer.WriteString(aurora.BrightCyan(fmt.Sprintf("echo PROG=goctl source %s >> ~/.zshrc && source ~/.zshrc", zshF)).String()) - case magic | flagBash: - buffer.WriteString(aurora.BrightCyan(fmt.Sprintf("echo PROG=goctl source %s >> ~/.bashrc && source ~/.bashrc", bashF)).String()) - case magic | flagZsh | flagBash: - buffer.WriteString(aurora.BrightCyan(fmt.Sprintf(`echo PROG=goctl source %s >> ~/.zshrc && source ~/.zshrc -or -echo PROG=goctl source %s >> ~/.bashrc && source ~/.bashrc`, zshF, bashF)).String()) - default: - return nil - } - - fmt.Println(buffer.String()) - return nil -} diff --git a/tools/goctl/completion/const.go b/tools/goctl/completion/const.go deleted file mode 100644 index 9a66c7462df7..000000000000 --- a/tools/goctl/completion/const.go +++ /dev/null @@ -1,12 +0,0 @@ -package completion - -const ( - BashCompletionFlag = `generate-goctl-completion` - defaultCompletionFilename = "goctl_autocomplete" -) - -const ( - magic = 1 << iota - flagZsh - flagBash -) diff --git a/tools/goctl/completion/script.go b/tools/goctl/completion/script.go deleted file mode 100644 index dfbd23090929..000000000000 --- a/tools/goctl/completion/script.go +++ /dev/null @@ -1,51 +0,0 @@ -package completion - -import "fmt" - -var zsh = []byte(fmt.Sprintf(`#compdef $PROG - -_cli_zsh_autocomplete() { - - local -a opts - local cur - cur=${words[-1]} - if [[ "$cur" == "-"* ]]; then - opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --%s)}") - else - opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --%s)}") - fi - - if [[ "${opts[1]}" != "" ]]; then - _describe 'values' opts - else - _files - fi - - return -} - -compdef _cli_zsh_autocomplete $PROG -`, BashCompletionFlag, BashCompletionFlag)) - -var bash = []byte(fmt.Sprintf(`#! /bin/bash - -: ${PROG:=$(basename ${BASH_SOURCE})} - -_cli_bash_autocomplete() { - if [[ "${COMP_WORDS[0]}" != "source" ]]; then - local cur opts base - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - if [[ "$cur" == "-"* ]]; then - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --%s ) - else - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --%s ) - fi - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - fi -} - -complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG -unset PROG -`, BashCompletionFlag, BashCompletionFlag)) diff --git a/tools/goctl/docker/cmd.go b/tools/goctl/docker/cmd.go new file mode 100644 index 000000000000..00ed6d59c612 --- /dev/null +++ b/tools/goctl/docker/cmd.go @@ -0,0 +1,32 @@ +package docker + +import "github.com/spf13/cobra" + +var ( + varStringGo string + varStringBase string + varIntPort int + varStringHome string + varStringRemote string + varStringBranch string + varStringVersion string + varStringTZ string + + // Cmd describes a docker command. + Cmd = &cobra.Command{ + Use: "docker", + Short: "Generate Dockerfile", + RunE: dockerCommand, + } +) + +func init() { + Cmd.Flags().StringVar(&varStringGo, "go", "", "The file that contains main function") + Cmd.Flags().StringVar(&varStringBase, "base", "scratch", "The base image to build the docker image, default scratch") + Cmd.Flags().IntVar(&varIntPort, "port", 0, "The port to expose, default none") + Cmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + Cmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + Cmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + Cmd.Flags().StringVar(&varStringVersion, "version", "", "The goctl builder golang image version") + Cmd.Flags().StringVar(&varStringTZ, "tz", "Asia/Shanghai", "The timezone of the container") +} diff --git a/tools/goctl/docker/docker.go b/tools/goctl/docker/docker.go index 8441db34107f..a2ab50ddfdfe 100644 --- a/tools/goctl/docker/docker.go +++ b/tools/goctl/docker/docker.go @@ -10,7 +10,7 @@ import ( "time" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -37,24 +37,20 @@ type Docker struct { Timezone string } -// DockerCommand provides the entry for goctl docker -func DockerCommand(c *cli.Context) (err error) { +// dockerCommand provides the entry for goctl docker +func dockerCommand(_ *cobra.Command, _ []string) (err error) { defer func() { if err == nil { fmt.Println(aurora.Green("Done.")) } }() - if c.NumFlags() == 0 { - cli.ShowCommandHelpAndExit(c, "docker", 1) - } - - goFile := c.String("go") - home := c.String("home") - version := c.String("version") - remote := c.String("remote") - branch := c.String("branch") - timezone := c.String("tz") + goFile := varStringGo + home := varStringHome + version := varStringVersion + remote := varStringRemote + branch := varStringBranch + timezone := varStringTZ if len(remote) > 0 { repo, _ := util.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -78,8 +74,8 @@ func DockerCommand(c *cli.Context) (err error) { return fmt.Errorf("file %q not found", goFile) } - base := c.String("base") - port := c.Int("port") + base := varStringBase + port := varIntPort if _, err := os.Stat(etcDir); os.IsNotExist(err) { return generateDockerfile(goFile, base, port, version, timezone) } diff --git a/tools/goctl/docker/template.go b/tools/goctl/docker/template.go index c18eab37b4e0..c51553a63c88 100644 --- a/tools/goctl/docker/template.go +++ b/tools/goctl/docker/template.go @@ -3,7 +3,6 @@ package docker import ( _ "embed" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -21,7 +20,7 @@ func Clean() error { } // GenTemplates creates docker template files -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return initTemplate() } diff --git a/tools/goctl/env/check.go b/tools/goctl/env/check.go index 45849f8bc0d7..af800fde48a2 100644 --- a/tools/goctl/env/check.go +++ b/tools/goctl/env/check.go @@ -5,7 +5,7 @@ import ( "strings" "time" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/pkg/env" "github.com/zeromicro/go-zero/tools/goctl/pkg/protoc" "github.com/zeromicro/go-zero/tools/goctl/pkg/protocgengo" @@ -37,11 +37,8 @@ var bins = []bin{ }, } -func Check(ctx *cli.Context) error { - install := ctx.Bool("install") - force := ctx.Bool("force") - verbose := ctx.Bool("verbose") - return Prepare(install, force, verbose) +func check(_ *cobra.Command, _ []string) error { + return Prepare(boolVarInstall, boolVarForce, boolVarVerbose) } func Prepare(install, force, verbose bool) error { diff --git a/tools/goctl/env/cmd.go b/tools/goctl/env/cmd.go new file mode 100644 index 000000000000..51decb964955 --- /dev/null +++ b/tools/goctl/env/cmd.go @@ -0,0 +1,46 @@ +package env + +import "github.com/spf13/cobra" + +var ( + sliceVarWriteValue []string + boolVarForce bool + boolVarVerbose bool + boolVarInstall bool + + // Cmd describes a env command. + Cmd = &cobra.Command{ + Use: "env", + Short: "Check or edit goctl environment", + RunE: write, + } + installCmd = &cobra.Command{ + Use: "install", + Short: "Goctl env installation", + RunE: install, + } + checkCmd = &cobra.Command{ + Use: "check", + Short: "Detect goctl env and dependency tools", + RunE: check, + } +) + +func init() { + // The root command flags + Cmd.Flags().StringSliceVarP(&sliceVarWriteValue, + "write", "w", nil, "Edit goctl environment") + Cmd.PersistentFlags().BoolVarP(&boolVarForce, + "force", "f", false, + "Silent installation of non-existent dependencies") + Cmd.PersistentFlags().BoolVarP(&boolVarVerbose, + "verbose", "v", false, "Enable log output") + + // The sub-command flags + checkCmd.Flags().BoolVarP(&boolVarInstall, "install", "i", + false, "Install dependencies if not found") + + // Add sub-command + Cmd.AddCommand(installCmd) + Cmd.AddCommand(checkCmd) +} diff --git a/tools/goctl/env/env.go b/tools/goctl/env/env.go index 04b468e2b905..a4cfae1f8b80 100644 --- a/tools/goctl/env/env.go +++ b/tools/goctl/env/env.go @@ -3,14 +3,13 @@ package env import ( "fmt" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/pkg/env" ) -func Action(c *cli.Context) error { - write := c.StringSlice("write") - if len(write) > 0 { - return env.WriteEnv(write) +func write(_ *cobra.Command, _ []string) error { + if len(sliceVarWriteValue) > 0 { + return env.WriteEnv(sliceVarWriteValue) } fmt.Println(env.Print()) return nil diff --git a/tools/goctl/env/install.go b/tools/goctl/env/install.go index 6edea2f1310c..0768a86877a2 100644 --- a/tools/goctl/env/install.go +++ b/tools/goctl/env/install.go @@ -1,9 +1,9 @@ package env -import "github.com/urfave/cli" +import ( + "github.com/spf13/cobra" +) -func Install(c *cli.Context) error { - force := c.Bool("force") - verbose := c.Bool("verbose") - return Prepare(true, force, verbose) +func install(_ *cobra.Command, _ []string) error { + return Prepare(true, boolVarForce, boolVarVerbose) } diff --git a/tools/goctl/go.mod b/tools/goctl/go.mod index 0cd2c3b69b8f..486c2763011c 100644 --- a/tools/goctl/go.mod +++ b/tools/goctl/go.mod @@ -9,8 +9,8 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/iancoleman/strcase v0.2.0 github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.0 - github.com/urfave/cli v1.22.5 github.com/zeromicro/antlr v0.0.1 github.com/zeromicro/ddl-parser v1.0.3 github.com/zeromicro/go-zero v1.3.2 diff --git a/tools/goctl/go.sum b/tools/goctl/go.sum index 29b24f110e72..e7f3e3b88fac 100644 --- a/tools/goctl/go.sum +++ b/tools/goctl/go.sum @@ -85,8 +85,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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= @@ -238,6 +238,8 @@ github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHL github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= @@ -344,9 +346,8 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -355,7 +356,10 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -367,8 +371,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= -github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= diff --git a/tools/goctl/goctl.go b/tools/goctl/goctl.go index 4c4511fece7f..5a0d5dfb5d80 100644 --- a/tools/goctl/goctl.go +++ b/tools/goctl/goctl.go @@ -1,958 +1,13 @@ package main import ( - "fmt" - "os" - "runtime" - - "github.com/logrusorgru/aurora" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/core/load" "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/tools/goctl/api/apigen" - "github.com/zeromicro/go-zero/tools/goctl/api/dartgen" - "github.com/zeromicro/go-zero/tools/goctl/api/docgen" - "github.com/zeromicro/go-zero/tools/goctl/api/format" - "github.com/zeromicro/go-zero/tools/goctl/api/gogen" - "github.com/zeromicro/go-zero/tools/goctl/api/javagen" - "github.com/zeromicro/go-zero/tools/goctl/api/ktgen" - "github.com/zeromicro/go-zero/tools/goctl/api/new" - "github.com/zeromicro/go-zero/tools/goctl/api/tsgen" - "github.com/zeromicro/go-zero/tools/goctl/api/validate" - "github.com/zeromicro/go-zero/tools/goctl/bug" - "github.com/zeromicro/go-zero/tools/goctl/completion" - "github.com/zeromicro/go-zero/tools/goctl/docker" - "github.com/zeromicro/go-zero/tools/goctl/env" - "github.com/zeromicro/go-zero/tools/goctl/internal/version" - "github.com/zeromicro/go-zero/tools/goctl/kube" - "github.com/zeromicro/go-zero/tools/goctl/migrate" - "github.com/zeromicro/go-zero/tools/goctl/model/mongo" - model "github.com/zeromicro/go-zero/tools/goctl/model/sql/command" - "github.com/zeromicro/go-zero/tools/goctl/plugin" - rpc "github.com/zeromicro/go-zero/tools/goctl/rpc/cli" - "github.com/zeromicro/go-zero/tools/goctl/tpl" - "github.com/zeromicro/go-zero/tools/goctl/upgrade" + "github.com/zeromicro/go-zero/tools/goctl/cmd" ) -const codeFailure = 1 - -var commands = []cli.Command{ - { - Name: "bug", - Usage: "report a bug", - Action: bug.Action, - }, - { - Name: "upgrade", - Usage: "upgrade goctl to latest version", - Action: upgrade.Upgrade, - }, - { - Name: "env", - Usage: "check or edit goctl environment", - Flags: []cli.Flag{ - cli.StringSliceFlag{ - Name: "write, w", - Usage: "edit goctl environment", - }, - }, - Subcommands: []cli.Command{ - { - Name: "install", - Usage: "goctl env installation", - Action: env.Install, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "force,f", - Usage: "silent installation of non-existent dependencies", - }, - cli.BoolFlag{ - Name: "verbose, v", - Usage: "enable log output", - }, - }, - }, - { - Name: "check", - Usage: "detect goctl env and dependency tools", - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "install, i", - Usage: "install dependencies if not found", - }, - cli.BoolFlag{ - Name: "force, f", - Usage: "silent installation of non-existent dependencies", - }, - cli.BoolFlag{ - Name: "verbose, v", - Usage: "enable log output", - }, - }, - Action: env.Check, - }, - }, - Action: env.Action, - }, - { - Name: "migrate", - Usage: "migrate from tal-tech to zeromicro", - Description: "migrate is a transition command to help users migrate their projects from tal-tech to zeromicro version", - Action: migrate.Migrate, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "verbose, v", - Usage: "verbose enables extra logging", - }, - cli.StringFlag{ - Name: "version", - Usage: "the target release version of github.com/zeromicro/go-zero to migrate", - }, - }, - }, - { - Name: "api", - Usage: "generate api related files", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "o", - Usage: "output a sample api file", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: apigen.ApiCommand, - Subcommands: []cli.Command{ - { - Name: "new", - Usage: "fast create api service", - UsageText: "example: goctl api new [options] service-name", - Action: new.CreateServiceCommand, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]", - }, - }, - }, - { - Name: "format", - Usage: "format api files", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the format target dir", - }, - cli.BoolFlag{ - Name: "iu", - Usage: "ignore update", - }, - cli.BoolFlag{ - Name: "stdin", - Usage: "use stdin to input api doc content, press \"ctrl + d\" to send EOF", - }, - cli.BoolFlag{ - Name: "declare", - Usage: "use to skip check api types already declare", - }, - }, - Action: format.GoFormatApi, - }, - { - Name: "validate", - Usage: "validate api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "api", - Usage: "validate target api file", - }, - }, - Action: validate.GoValidateApi, - }, - { - Name: "doc", - Usage: "generate doc files", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "o", - Required: false, - Usage: "the output markdown directory", - }, - }, - Action: docgen.DocCommand, - }, - { - Name: "go", - Usage: "generate go files for provided api in api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: gogen.GoCommand, - }, - { - Name: "java", - Usage: "generate java files for provided api in api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - }, - Action: javagen.JavaCommand, - }, - { - Name: "ts", - Usage: "generate ts files for provided api in api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - cli.StringFlag{ - Name: "webapi", - Usage: "the web api file path", - }, - cli.StringFlag{ - Name: "caller", - Usage: "the web api caller", - }, - cli.BoolFlag{ - Name: "unwrap", - Usage: "unwrap the webapi caller for import", - }, - }, - Action: tsgen.TsCommand, - }, - { - Name: "dart", - Usage: "generate dart files for provided api in api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - cli.BoolFlag{ - Name: "legacy", - Usage: "legacy generator for flutter v1", - }, - cli.StringFlag{ - Name: "hostname", - Usage: "hostname of the server", - }, - }, - Action: dartgen.DartCommand, - }, - { - Name: "kt", - Usage: "generate kotlin code for provided api file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "dir", - Usage: "the target directory", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - cli.StringFlag{ - Name: "pkg", - Usage: "define package name for kotlin file", - }, - }, - Action: ktgen.KtCommand, - }, - { - Name: "plugin", - Usage: "custom file generator", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "plugin, p", - Usage: "the plugin file", - }, - cli.StringFlag{ - Name: "dir", - Usage: "the target directory", - }, - cli.StringFlag{ - Name: "api", - Usage: "the api file", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - }, - Action: plugin.PluginCommand, - }, - }, - }, - { - Name: "docker", - Usage: "generate Dockerfile", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "go", - Usage: "the file that contains main function", - }, - cli.StringFlag{ - Name: "base", - Usage: "the base image to build the docker image, default scratch", - Value: "scratch", - }, - cli.IntFlag{ - Name: "port", - Usage: "the port to expose, default none", - Value: 0, - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - cli.StringFlag{ - Name: "version", - Usage: "the goctl builder golang image version", - }, - cli.StringFlag{ - Name: "tz", - Usage: "the timezone of the container", - Value: "Asia/Shanghai", - }, - }, - Action: docker.DockerCommand, - }, - { - Name: "kube", - Usage: "generate kubernetes files", - Subcommands: []cli.Command{ - { - Name: "deploy", - Usage: "generate deployment yaml file", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "name", - Usage: "the name of deployment", - Required: true, - }, - cli.StringFlag{ - Name: "namespace", - Usage: "the namespace of deployment", - Required: true, - }, - cli.StringFlag{ - Name: "image", - Usage: "the docker image of deployment", - Required: true, - }, - cli.StringFlag{ - Name: "secret", - Usage: "the secret to image pull from registry", - }, - cli.IntFlag{ - Name: "requestCpu", - Usage: "the request cpu to deploy", - Value: 500, - }, - cli.IntFlag{ - Name: "requestMem", - Usage: "the request memory to deploy", - Value: 512, - }, - cli.IntFlag{ - Name: "limitCpu", - Usage: "the limit cpu to deploy", - Value: 1000, - }, - cli.IntFlag{ - Name: "limitMem", - Usage: "the limit memory to deploy", - Value: 1024, - }, - cli.StringFlag{ - Name: "o", - Usage: "the output yaml file", - Required: true, - }, - cli.IntFlag{ - Name: "replicas", - Usage: "the number of replicas to deploy", - Value: 3, - }, - cli.IntFlag{ - Name: "revisions", - Usage: "the number of revision history to limit", - Value: 5, - }, - cli.IntFlag{ - Name: "port", - Usage: "the port of the deployment to listen on pod", - Required: true, - }, - cli.IntFlag{ - Name: "nodePort", - Usage: "the nodePort of the deployment to expose", - Value: 0, - }, - cli.IntFlag{ - Name: "minReplicas", - Usage: "the min replicas to deploy", - Value: 3, - }, - cli.IntFlag{ - Name: "maxReplicas", - Usage: "the max replicas of deploy", - Value: 10, - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - cli.StringFlag{ - Name: "serviceAccount", - Usage: "the ServiceAccount for the deployment", - }, - }, - Action: kube.DeploymentCommand, - }, - }, - }, - { - Name: "rpc", - Usage: "generate rpc code", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "o", - Usage: "output a sample proto file", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: rpc.RPCTemplate, - Subcommands: []cli.Command{ - { - Name: "new", - Usage: `generate rpc demo service`, - UsageText: "example: goctl rpc new [options] service-name", - Flags: []cli.Flag{ - cli.StringSliceFlag{ - Name: "go_opt", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "go-grpc_opt", - Hidden: true, - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.BoolFlag{ - Name: "idea", - Usage: "whether the command execution environment is from idea plugin. [optional]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - cli.BoolFlag{ - Name: "verbose, v", - Usage: "enable log output", - }, - }, - Action: rpc.RPCNew, - }, - { - Name: "template", - Usage: `generate proto template`, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "out, o", - Usage: "the target path of proto (deprecated)", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time," + - " if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: rpc.RPCTemplate, - }, - { - Name: "protoc", - Usage: "generate grpc code", - UsageText: `example: goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.`, - Description: "for details, see https://go-zero.dev/cn/goctl-rpc.html", - Action: rpc.ZRPC, - Flags: []cli.Flag{ - cli.StringSliceFlag{ - Name: "go_out", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "go-grpc_out", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "go_opt", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "go-grpc_opt", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "plugin", - Hidden: true, - }, - cli.StringSliceFlag{ - Name: "proto_path,I", - Hidden: true, - }, - cli.StringFlag{ - Name: "zrpc_out", - Usage: "the zrpc output directory", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - cli.BoolFlag{ - Name: "verbose, v", - Usage: "enable log output", - }, - }, - }, - }, - }, - { - Name: "model", - Usage: "generate model code", - Subcommands: []cli.Command{ - { - Name: "mysql", - Usage: `generate mysql model`, - Subcommands: []cli.Command{ - { - Name: "ddl", - Usage: `generate mysql model from ddl`, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "src, s", - Usage: "the path or path globbing patterns of the ddl", - }, - cli.StringFlag{ - Name: "dir, d", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.BoolFlag{ - Name: "cache, c", - Usage: "generate code with cache [optional]", - }, - cli.BoolFlag{ - Name: "idea", - Usage: "for idea plugin [optional]", - }, - cli.StringFlag{ - Name: "database, db", - Usage: "the name of database [optional]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: model.MysqlDDL, - }, - { - Name: "datasource", - Usage: `generate model from datasource`, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "url", - Usage: `the data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`, - }, - cli.StringSliceFlag{ - Name: "table, t", - Usage: `the table or table globbing patterns in the database`, - }, - cli.BoolFlag{ - Name: "cache, c", - Usage: "generate code with cache [optional]", - }, - cli.StringFlag{ - Name: "dir, d", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.BoolFlag{ - Name: "idea", - Usage: "for idea plugin [optional]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: model.MySqlDataSource, - }, - }, - }, - { - Name: "pg", - Usage: `generate postgresql model`, - Subcommands: []cli.Command{ - { - Name: "datasource", - Usage: `generate model from datasource`, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "url", - Usage: `the data source of database,like "postgres://root:password@127.0.0.1:5432/database?sslmode=disable"`, - }, - cli.StringFlag{ - Name: "table, t", - Usage: `the table or table globbing patterns in the database`, - }, - cli.StringFlag{ - Name: "schema, s", - Usage: `the table schema, default is [public]`, - }, - cli.BoolFlag{ - Name: "cache, c", - Usage: "generate code with cache [optional]", - }, - cli.StringFlag{ - Name: "dir, d", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.BoolFlag{ - Name: "idea", - Usage: "for idea plugin [optional]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: model.PostgreSqlDataSource, - }, - }, - }, - { - Name: "mongo", - Usage: `generate mongo model`, - Flags: []cli.Flag{ - cli.StringSliceFlag{ - Name: "type, t", - Usage: "specified model type name", - }, - cli.BoolFlag{ - Name: "cache, c", - Usage: "generate code with cache [optional]", - }, - cli.StringFlag{ - Name: "dir, d", - Usage: "the target dir", - }, - cli.StringFlag{ - Name: "style", - Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template, --home and --remote cannot be set at the same time," + - " if they are, --remote has higher priority", - }, - cli.StringFlag{ - Name: "remote", - Usage: "the remote git repo of the template, --home and --remote cannot be set at the same time, " + - "if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the " + - "https://github.com/zeromicro/go-zero-template directory structure", - }, - cli.StringFlag{ - Name: "branch", - Usage: "the branch of the remote repo, it does work with --remote", - }, - }, - Action: mongo.Action, - }, - }, - }, - { - Name: "template", - Usage: "template operation", - Subcommands: []cli.Command{ - { - Name: "init", - Usage: "initialize the all templates(force update)", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template", - }, - }, - Action: tpl.GenTemplates, - }, - { - Name: "clean", - Usage: "clean the all cache templates", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template", - }, - }, - Action: tpl.CleanTemplates, - }, - { - Name: "update", - Usage: "update template of the target category to the latest", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "category,c", - Usage: "the category of template, enum [api,rpc,model,docker,kube]", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template", - }, - }, - Action: tpl.UpdateTemplates, - }, - { - Name: "revert", - Usage: "revert the target template to the latest", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "category,c", - Usage: "the category of template, enum [api,rpc,model,docker,kube]", - }, - cli.StringFlag{ - Name: "name,n", - Usage: "the target file name of template", - }, - cli.StringFlag{ - Name: "home", - Usage: "the goctl home path of the template", - }, - }, - Action: tpl.RevertTemplates, - }, - }, - }, - { - Name: "completion", - Usage: "generation completion script, it only works for unix-like OS", - Action: completion.Completion, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "name, n", - Usage: "the filename of auto complete script, default is [goctl_autocomplete]", - }, - }, - }, -} - func main() { logx.Disable() load.Disable() - - cli.BashCompletionFlag = cli.BoolFlag{ - Name: completion.BashCompletionFlag, - Hidden: true, - } - app := cli.NewApp() - app.EnableBashCompletion = true - app.Usage = "a cli tool to generate code" - app.Version = fmt.Sprintf("%s %s/%s", version.BuildVersion, runtime.GOOS, runtime.GOARCH) - app.Commands = commands - - // cli already print error messages. - if err := app.Run(os.Args); err != nil { - fmt.Println(aurora.Red(err.Error())) - os.Exit(codeFailure) - } + cmd.Execute() } diff --git a/tools/goctl/internal/version/version.go b/tools/goctl/internal/version/version.go index 1bbbe76ef78a..94500b5c33f2 100644 --- a/tools/goctl/internal/version/version.go +++ b/tools/goctl/internal/version/version.go @@ -6,7 +6,7 @@ import ( ) // BuildVersion is the version of goctl. -const BuildVersion = "1.3.5" +const BuildVersion = "1.3.6-beta" var tag = map[string]int{"pre-alpha": 0, "alpha": 1, "pre-bata": 2, "beta": 3, "released": 4, "": 5} diff --git a/tools/goctl/kube/cmd.go b/tools/goctl/kube/cmd.go new file mode 100644 index 000000000000..98d2a6da2e81 --- /dev/null +++ b/tools/goctl/kube/cmd.go @@ -0,0 +1,71 @@ +package kube + +import "github.com/spf13/cobra" + +var ( + varStringName string + varStringNamespace string + varStringImage string + varStringSecret string + varIntRequestCpu int + varIntRequestMem int + varIntLimitCpu int + varIntLimitMem int + varStringO string + varIntReplicas int + varIntRevisions int + varIntPort int + varIntNodePort int + varIntMinReplicas int + varIntMaxReplicas int + varStringHome string + varStringRemote string + varStringBranch string + varStringServiceAccount string + + // Cmd describes a kube command. + Cmd = &cobra.Command{ + Use: "kube", + Short: "Generate kubernetes files", + } + + deployCmd = &cobra.Command{ + Use: "deploy", + Short: "Generate deployment yaml file", + RunE: deploymentCommand, + } +) + +func init() { + deployCmd.Flags().StringVar(&varStringName, "name", "", "The name of deployment (required)") + deployCmd.Flags().StringVar(&varStringNamespace, "namespace", "", "The namespace of deployment (required)") + deployCmd.Flags().StringVar(&varStringImage, "image", "", "The docker image of deployment (required)") + deployCmd.Flags().StringVar(&varStringSecret, "secret", "", "The secret to image pull from registry") + deployCmd.Flags().IntVar(&varIntRequestCpu, "requestCpu", 500, "The request cpu to deploy") + deployCmd.Flags().IntVar(&varIntRequestMem, "requestMem", 512, "The request memory to deploy") + deployCmd.Flags().IntVar(&varIntLimitCpu, "limitCpu", 1000, "The limit cpu to deploy") + deployCmd.Flags().IntVar(&varIntLimitMem, "limitMem", 1024, "The limit memory to deploy") + deployCmd.Flags().StringVar(&varStringO, "o", "", "The output yaml file (required)") + deployCmd.Flags().IntVar(&varIntReplicas, "replicas", 3, "The number of replicas to deploy") + deployCmd.Flags().IntVar(&varIntRevisions, "revisions", 5, "The number of revision history to limit") + deployCmd.Flags().IntVar(&varIntPort, "port", 0, "The port of the deployment to listen on pod (required)") + deployCmd.Flags().IntVar(&varIntNodePort, "nodePort", 0, "The nodePort of the deployment to expose") + deployCmd.Flags().IntVar(&varIntMinReplicas, "minReplicas", 3, "The min replicas to deploy") + deployCmd.Flags().IntVar(&varIntMaxReplicas, "maxReplicas", 10, "The max replicas to deploy") + + deployCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority") + deployCmd.Flags().StringVar(&varStringRemote, "remote", "", "The remote git repo of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo "+ + "directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + deployCmd.Flags().StringVar(&varStringBranch, "branch", "", "The branch of the remote repo, it "+ + "does work with --remote") + deployCmd.Flags().StringVar(&varStringServiceAccount, "serviceAccount", "", "The ServiceAccount "+ + "for the deployment") + deployCmd.MarkFlagRequired("name") + deployCmd.MarkFlagRequired("namespace") + deployCmd.MarkFlagRequired("o") + deployCmd.MarkFlagRequired("port") + + Cmd.AddCommand(deployCmd) +} diff --git a/tools/goctl/kube/kube.go b/tools/goctl/kube/kube.go index 060ce6520c4e..0c38b991269b 100644 --- a/tools/goctl/kube/kube.go +++ b/tools/goctl/kube/kube.go @@ -7,7 +7,7 @@ import ( "text/template" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -48,11 +48,11 @@ type Deployment struct { } // DeploymentCommand is used to generate the kubernetes deployment yaml files. -func DeploymentCommand(c *cli.Context) error { - nodePort := c.Int("nodePort") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") +func deploymentCommand(_ *cobra.Command, _ []string) error { + nodePort := varIntNodePort + home := varStringHome + remote := varStringRemote + branch := varStringBranch if len(remote) > 0 { repo, _ := util.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -74,7 +74,7 @@ func DeploymentCommand(c *cli.Context) error { return err } - out, err := pathx.CreateIfNotExist(c.String("o")) + out, err := pathx.CreateIfNotExist(varStringO) if err != nil { return err } @@ -82,22 +82,22 @@ func DeploymentCommand(c *cli.Context) error { t := template.Must(template.New("deploymentTemplate").Parse(text)) err = t.Execute(out, Deployment{ - Name: c.String("name"), - Namespace: c.String("namespace"), - Image: c.String("image"), - Secret: c.String("secret"), - Replicas: c.Int("replicas"), - Revisions: c.Int("revisions"), - Port: c.Int("port"), + Name: varStringName, + Namespace: varStringNamespace, + Image: varStringImage, + Secret: varStringSecret, + Replicas: varIntReplicas, + Revisions: varIntRevisions, + Port: varIntPort, NodePort: nodePort, UseNodePort: nodePort > 0, - RequestCpu: c.Int("requestCpu"), - RequestMem: c.Int("requestMem"), - LimitCpu: c.Int("limitCpu"), - LimitMem: c.Int("limitMem"), - MinReplicas: c.Int("minReplicas"), - MaxReplicas: c.Int("maxReplicas"), - ServiceAccount: c.String("serviceAccount"), + RequestCpu: varIntRequestCpu, + RequestMem: varIntRequestMem, + LimitCpu: varIntLimitCpu, + LimitMem: varIntLimitMem, + MinReplicas: varIntMinReplicas, + MaxReplicas: varIntMaxReplicas, + ServiceAccount: varStringServiceAccount, }) if err != nil { return err @@ -118,7 +118,7 @@ func Clean() error { } // GenTemplates generates the deployment template files. -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, map[string]string{ deployTemplateFile: deploymentTemplate, jobTemplateFile: jobTemplate, diff --git a/tools/goctl/migrate/cmd.go b/tools/goctl/migrate/cmd.go new file mode 100644 index 000000000000..48ca10700012 --- /dev/null +++ b/tools/goctl/migrate/cmd.go @@ -0,0 +1,23 @@ +package migrate + +import "github.com/spf13/cobra" + +var ( + boolVarVerbose bool + stringVarVersion string + // Cmd describes a migrate command. + Cmd = &cobra.Command{ + Use: "migrate", + Short: "Migrate from tal-tech to zeromicro", + Long: "Migrate is a transition command to help users migrate their " + + "projects from tal-tech to zeromicro version", + RunE: migrate, + } +) + +func init() { + Cmd.Flags().BoolVarP(&boolVarVerbose, "verbose", "v", + false, "Verbose enables extra logging") + Cmd.Flags().StringVar(&stringVarVersion, "version", defaultMigrateVersion, + "The target release version of github.com/zeromicro/go-zero to migrate") +} diff --git a/tools/goctl/migrate/migrate.go b/tools/goctl/migrate/migrate.go index 6094a688c0c6..f6c5bcfbfb8b 100644 --- a/tools/goctl/migrate/migrate.go +++ b/tools/goctl/migrate/migrate.go @@ -16,13 +16,13 @@ import ( "time" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/util/console" "github.com/zeromicro/go-zero/tools/goctl/util/ctx" "github.com/zeromicro/go-zero/tools/goctl/vars" ) -const zeromicroVersion = "v1.3.0" +const defaultMigrateVersion = "v1.3.0" const ( confirmUnknown = iota @@ -35,28 +35,26 @@ var ( builderxConfirm = confirmUnknown ) -func Migrate(c *cli.Context) error { - verbose := c.Bool("verbose") - version := c.String("version") - if len(version) == 0 { - version = zeromicroVersion +func migrate(_ *cobra.Command, _ []string) error { + if len(stringVarVersion) == 0 { + stringVarVersion = defaultMigrateVersion } - err := editMod(version, verbose) + err := editMod(stringVarVersion, boolVarVerbose) if err != nil { return err } - err = rewriteImport(verbose) + err = rewriteImport(boolVarVerbose) if err != nil { return err } - err = tidy(verbose) + err = tidy(boolVarVerbose) if err != nil { return err } - if verbose { + if boolVarVerbose { console.Success("[OK] refactor finish, execute %q on project root to check status.", "go test -race ./...") } diff --git a/tools/goctl/model/cmd.go b/tools/goctl/model/cmd.go new file mode 100644 index 000000000000..9dd1746f762a --- /dev/null +++ b/tools/goctl/model/cmd.go @@ -0,0 +1,91 @@ +package model + +import ( + "github.com/spf13/cobra" + "github.com/zeromicro/go-zero/tools/goctl/model/mongo" + "github.com/zeromicro/go-zero/tools/goctl/model/sql/command" +) + +var ( + // Cmd describes a model command. + Cmd = &cobra.Command{ + Use: "model", + Short: "Generate model code", + } + + mysqlCmd = &cobra.Command{ + Use: "mysql", + Short: "Generate mysql model", + } + + ddlCmd = &cobra.Command{ + Use: "ddl", + Short: "Generate mysql model from ddl", + RunE: command.MysqlDDL, + } + + datasourceCmd = &cobra.Command{ + Use: "datasource", + Short: "Generate model from datasource", + RunE: command.MySqlDataSource, + } + + pgCmd = &cobra.Command{ + Use: "pg", + Short: "Generate postgresql model", + RunE: command.PostgreSqlDataSource, + } + + mongoCmd = &cobra.Command{ + Use: "mongo", + Short: "Generate mongo model", + RunE: mongo.Action, + } +) + +func init() { + ddlCmd.Flags().StringVarP(&command.VarStringSrc, "src", "s", "", "The path or path globbing patterns of the ddl") + ddlCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") + ddlCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + ddlCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") + ddlCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") + ddlCmd.Flags().StringVar(&command.VarStringDatabase, "database", "", "The name of database [optional]") + ddlCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + ddlCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + ddlCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + datasourceCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`) + datasourceCmd.Flags().StringSliceVarP(&command.VarStringSliceTable, "table", "t", nil, "The table or table globbing patterns in the database") + datasourceCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") + datasourceCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") + datasourceCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + datasourceCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") + datasourceCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + datasourceCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + datasourceCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + pgCmd.Flags().StringVar(&command.VarStringURL, "url", "", `The data source of database,like "root:password@tcp(127.0.0.1:3306)/database"`) + pgCmd.Flags().StringVarP(&command.VarStringTable, "table", "t", "", "The table or table globbing patterns in the database") + pgCmd.Flags().StringVarP(&command.VarStringSchema, "schema", "s", "public", "The table schema") + pgCmd.Flags().BoolVarP(&command.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") + pgCmd.Flags().StringVarP(&command.VarStringDir, "dir", "d", "", "The target dir") + pgCmd.Flags().StringVar(&command.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + pgCmd.Flags().BoolVar(&command.VarBoolIdea, "idea", false, "For idea plugin [optional]") + pgCmd.Flags().StringVar(&command.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + pgCmd.Flags().StringVar(&command.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + pgCmd.Flags().StringVar(&command.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + mongoCmd.Flags().StringSliceVarP(&mongo.VarStringSliceType, "type", "t", nil, "Specified model type name") + mongoCmd.Flags().BoolVarP(&mongo.VarBoolCache, "cache", "c", false, "Generate code with cache [optional]") + mongoCmd.Flags().StringVarP(&mongo.VarStringDir, "dir", "d", "", "The target dir") + mongoCmd.Flags().StringVar(&mongo.VarStringStyle, "style", "", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + mongoCmd.Flags().StringVar(&mongo.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + mongoCmd.Flags().StringVar(&mongo.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + mongoCmd.Flags().StringVar(&mongo.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + mysqlCmd.AddCommand(datasourceCmd) + mysqlCmd.AddCommand(ddlCmd) + mysqlCmd.AddCommand(pgCmd) + Cmd.AddCommand(mysqlCmd) + Cmd.AddCommand(mongoCmd) +} diff --git a/tools/goctl/model/mongo/generate/template.go b/tools/goctl/model/mongo/generate/template.go index 644250e837ce..a86f96d8d166 100644 --- a/tools/goctl/model/mongo/generate/template.go +++ b/tools/goctl/model/mongo/generate/template.go @@ -3,7 +3,6 @@ package generate import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/model/mongo/template" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -30,7 +29,7 @@ func Clean() error { } // Templates initializes the mongo templates. -func Templates(_ *cli.Context) error { +func Templates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/model/mongo/mongo.go b/tools/goctl/model/mongo/mongo.go index 861c804f2507..ab3d4ae6ba06 100644 --- a/tools/goctl/model/mongo/mongo.go +++ b/tools/goctl/model/mongo/mongo.go @@ -5,22 +5,39 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/model/mongo/generate" file "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) +var ( + // VarStringSliceType describes a golang data structure name for mongo. + VarStringSliceType []string + // VarStringDir describes an output directory. + VarStringDir string + // VarBoolCache describes whether cache is enabled. + VarBoolCache bool + // VarStringStyle describes the style. + VarStringStyle string + // VarStringHome describes the goctl home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the git branch. + VarStringBranch string +) + // Action provides the entry for goctl mongo code generation. -func Action(ctx *cli.Context) error { - tp := ctx.StringSlice("type") - c := ctx.Bool("cache") - o := strings.TrimSpace(ctx.String("dir")) - s := ctx.String("style") - home := ctx.String("home") - remote := ctx.String("remote") - branch := ctx.String("branch") +func Action(_ *cobra.Command, _ []string) error { + tp := VarStringSliceType + c := VarBoolCache + o := strings.TrimSpace(VarStringDir) + s := VarStringStyle + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := file.CloneIntoGitHome(remote, branch) if len(repo) > 0 { diff --git a/tools/goctl/model/sql/command/command.go b/tools/goctl/model/sql/command/command.go index eac3f0149f94..9fd65777d8c7 100644 --- a/tools/goctl/model/sql/command/command.go +++ b/tools/goctl/model/sql/command/command.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/go-sql-driver/mysql" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/postgres" "github.com/zeromicro/go-zero/core/stores/sqlx" @@ -20,35 +20,49 @@ import ( "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) -const ( - flagSrc = "src" - flagDir = "dir" - flagCache = "cache" - flagIdea = "idea" - flagURL = "url" - flagTable = "table" - flagStyle = "style" - flagDatabase = "database" - flagSchema = "schema" - flagHome = "home" - flagRemote = "remote" - flagBranch = "branch" +var ( + // VarStringSrc describes the source file of sql. + VarStringSrc string + // VarStringDir describes the output directory of sql. + VarStringDir string + // VarBoolCache describes whether the cache is enabled. + VarBoolCache bool + // VarBoolIdea describes whether is idea or not. + VarBoolIdea bool + // VarStringURL describes the dsn of the sql. + VarStringURL string + // VarStringSliceTable describes tables. + VarStringSliceTable []string + // VarStringTable describes a table of sql. + VarStringTable string + // VarStringStyle describes the style. + VarStringStyle string + // VarStringDatabase describes the database. + VarStringDatabase string + // VarStringSchema describes the schema of postgresql. + VarStringSchema string + // VarStringHome describes the goctl home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the git branch of the repository. + VarStringBranch string ) var errNotMatched = errors.New("sql not matched") // MysqlDDL generates model code from ddl -func MysqlDDL(ctx *cli.Context) error { - migrationnotes.BeforeCommands(ctx) - src := ctx.String(flagSrc) - dir := ctx.String(flagDir) - cache := ctx.Bool(flagCache) - idea := ctx.Bool(flagIdea) - style := ctx.String(flagStyle) - database := ctx.String(flagDatabase) - home := ctx.String(flagHome) - remote := ctx.String(flagRemote) - branch := ctx.String(flagBranch) +func MysqlDDL(_ *cobra.Command, _ []string) error { + migrationnotes.BeforeCommands(VarStringDir, VarStringStyle) + src := VarStringSrc + dir := VarStringDir + cache := VarBoolCache + idea := VarBoolIdea + style := VarStringStyle + database := VarStringDatabase + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := file.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -67,16 +81,16 @@ func MysqlDDL(ctx *cli.Context) error { } // MySqlDataSource generates model code from datasource -func MySqlDataSource(ctx *cli.Context) error { - migrationnotes.BeforeCommands(ctx) - url := strings.TrimSpace(ctx.String(flagURL)) - dir := strings.TrimSpace(ctx.String(flagDir)) - cache := ctx.Bool(flagCache) - idea := ctx.Bool(flagIdea) - style := ctx.String(flagStyle) - home := ctx.String(flagHome) - remote := ctx.String(flagRemote) - branch := ctx.String(flagBranch) +func MySqlDataSource(_ *cobra.Command, _ []string) error { + migrationnotes.BeforeCommands(VarStringDir, VarStringStyle) + url := strings.TrimSpace(VarStringURL) + dir := strings.TrimSpace(VarStringDir) + cache := VarBoolCache + idea := VarBoolIdea + style := VarStringStyle + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := file.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -87,7 +101,7 @@ func MySqlDataSource(ctx *cli.Context) error { pathx.RegisterGoctlHome(home) } - tableValue := ctx.StringSlice(flagTable) + tableValue := VarStringSliceTable patterns := parseTableList(tableValue) cfg, err := config.NewConfig(style) if err != nil { @@ -135,17 +149,17 @@ func parseTableList(tableValue []string) pattern { } // PostgreSqlDataSource generates model code from datasource -func PostgreSqlDataSource(ctx *cli.Context) error { - migrationnotes.BeforeCommands(ctx) - url := strings.TrimSpace(ctx.String(flagURL)) - dir := strings.TrimSpace(ctx.String(flagDir)) - cache := ctx.Bool(flagCache) - idea := ctx.Bool(flagIdea) - style := ctx.String(flagStyle) - schema := ctx.String(flagSchema) - home := ctx.String(flagHome) - remote := ctx.String(flagRemote) - branch := ctx.String(flagBranch) +func PostgreSqlDataSource(_ *cobra.Command, _ []string) error { + migrationnotes.BeforeCommands(VarStringDir, VarStringStyle) + url := strings.TrimSpace(VarStringURL) + dir := strings.TrimSpace(VarStringDir) + cache := VarBoolCache + idea := VarBoolIdea + style := VarStringStyle + schema := VarStringSchema + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := file.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -160,7 +174,7 @@ func PostgreSqlDataSource(ctx *cli.Context) error { schema = "public" } - pattern := strings.TrimSpace(ctx.String(flagTable)) + pattern := strings.TrimSpace(VarStringTable) cfg, err := config.NewConfig(style) if err != nil { return err diff --git a/tools/goctl/model/sql/command/migrationnotes/migrationnotes.go b/tools/goctl/model/sql/command/migrationnotes/migrationnotes.go index d8baa62edaef..8de49a5900ed 100644 --- a/tools/goctl/model/sql/command/migrationnotes/migrationnotes.go +++ b/tools/goctl/model/sql/command/migrationnotes/migrationnotes.go @@ -1,14 +1,13 @@ package migrationnotes import ( - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/util/format" ) // BeforeCommands run before comamnd run to show some migration notes -func BeforeCommands(ctx *cli.Context) error { - if err := migrateBefore1_3_4(ctx); err != nil { +func BeforeCommands(dir, style string) error { + if err := migrateBefore1_3_4(dir, style); err != nil { return err } return nil diff --git a/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go b/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go index 2a99e142f6bc..8b63b173092f 100644 --- a/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go +++ b/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go @@ -4,13 +4,9 @@ import ( "fmt" "io/ioutil" "strings" - - "github.com/urfave/cli" ) -func migrateBefore1_3_4(ctx *cli.Context) error { - dir := ctx.String("dir") - style := ctx.String("style") +func migrateBefore1_3_4(dir, style string) error { ok, err := needShow1_3_4(dir, style) if err != nil { return err diff --git a/tools/goctl/model/sql/gen/template.go b/tools/goctl/model/sql/gen/template.go index e2cecdbaae3b..19513ffc9c73 100644 --- a/tools/goctl/model/sql/gen/template.go +++ b/tools/goctl/model/sql/gen/template.go @@ -3,7 +3,6 @@ package gen import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/model/sql/template" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -70,7 +69,7 @@ func Clean() error { } // GenTemplates creates template files if not exists -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/plugin/plugin.go b/tools/goctl/plugin/plugin.go index 50ea181e874d..321d6132bc12 100644 --- a/tools/goctl/plugin/plugin.go +++ b/tools/goctl/plugin/plugin.go @@ -13,7 +13,7 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/rpc/execx" @@ -30,19 +30,30 @@ type Plugin struct { Dir string } +var ( + // VarStringPlugin describes a plugin. + VarStringPlugin string + // VarStringDir describes a directory. + VarStringDir string + // VarStringAPI describes an API file. + VarStringAPI string + // VarStringStyle describes a style. + VarStringStyle string +) + // PluginCommand is the entry of goctl api plugin -func PluginCommand(c *cli.Context) error { +func PluginCommand(_ *cobra.Command, _ []string) error { ex, err := os.Executable() if err != nil { panic(err) } - plugin := c.String("plugin") + plugin := VarStringPlugin if len(plugin) == 0 { return errors.New("missing plugin") } - transferData, err := prepareArgs(c) + transferData, err := prepareArgs() if err != nil { return err } @@ -69,8 +80,8 @@ func PluginCommand(c *cli.Context) error { return nil } -func prepareArgs(c *cli.Context) ([]byte, error) { - apiPath := c.String("api") +func prepareArgs() ([]byte, error) { + apiPath := VarStringAPI var transferData Plugin if len(apiPath) > 0 && pathx.FileExists(apiPath) { @@ -88,13 +99,13 @@ func prepareArgs(c *cli.Context) ([]byte, error) { } transferData.ApiFilePath = absApiFilePath - dirAbs, err := filepath.Abs(c.String("dir")) + dirAbs, err := filepath.Abs(VarStringDir) if err != nil { return nil, err } transferData.Dir = dirAbs - transferData.Style = c.String("style") + transferData.Style = VarStringStyle data, err := json.Marshal(transferData) if err != nil { return nil, err diff --git a/tools/goctl/rpc/cli/cli.go b/tools/goctl/rpc/cli/cli.go index f625f29bddb1..c65369916c19 100644 --- a/tools/goctl/rpc/cli/cli.go +++ b/tools/goctl/rpc/cli/cli.go @@ -6,30 +6,57 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/rpc/generator" "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/console" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) +var ( + // VarStringOutput describes the output. + VarStringOutput string + // VarStringHome describes the goctl home. + VarStringHome string + // VarStringRemote describes the remote git repository. + VarStringRemote string + // VarStringBranch describes the git branch. + VarStringBranch string + // VarStringSliceGoOut describes the go output. + VarStringSliceGoOut []string + // VarStringSliceGoGRPCOut describes the grpc output. + VarStringSliceGoGRPCOut []string + // VarStringSlicePlugin describes the protoc plugin. + VarStringSlicePlugin []string + // VarStringSliceProtoPath describes the proto path. + VarStringSliceProtoPath []string + // VarStringSliceGoOpt describes the go options. + VarStringSliceGoOpt []string + // VarStringSliceGoGRPCOpt describes the grpc options. + VarStringSliceGoGRPCOpt []string + // VarStringStyle describes the style of output files. + VarStringStyle string + // VarStringZRPCOut describes the zRPC output. + VarStringZRPCOut string + // VarBoolIdea describes whether idea or not + VarBoolIdea bool + // VarBoolVerbose describes whether verbose. + VarBoolVerbose bool +) + // RPCNew is to generate rpc greet service, this greet service can speed // up your understanding of the zrpc service structure -func RPCNew(c *cli.Context) error { - if c.NArg() == 0 { - cli.ShowCommandHelpAndExit(c, "new", 1) - } - - rpcname := c.Args().First() +func RPCNew(_ *cobra.Command, args []string) error { + rpcname := args[0] ext := filepath.Ext(rpcname) if len(ext) > 0 { return fmt.Errorf("unexpected ext: %s", ext) } - style := c.String("style") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") - verbose := c.Bool("verbose") + style := VarStringStyle + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch + verbose := VarBoolVerbose if len(remote) > 0 { repo, _ := util.CloneIntoGitHome(remote, branch) if len(repo) > 0 { @@ -60,12 +87,12 @@ func RPCNew(c *cli.Context) error { ctx.Output = filepath.Dir(src) ctx.ProtocCmd = fmt.Sprintf("protoc -I=%s %s --go_out=%s --go-grpc_out=%s", filepath.Dir(src), filepath.Base(src), filepath.Dir(src), filepath.Dir(src)) - grpcOptList := c.StringSlice("go-grpc_opt") + grpcOptList := VarStringSliceGoGRPCOpt if len(grpcOptList) > 0 { ctx.ProtocCmd += " --go-grpc_opt=" + strings.Join(grpcOptList, ",") } - goOptList := c.StringSlice("go_opt") + goOptList := VarStringSliceGoOpt if len(goOptList) > 0 { ctx.ProtocCmd += " --go_opt=" + strings.Join(goOptList, ",") } @@ -75,17 +102,12 @@ func RPCNew(c *cli.Context) error { } // RPCTemplate is the entry for generate rpc template -func RPCTemplate(c *cli.Context) error { +func RPCTemplate(_ *cobra.Command, _ []string) error { console.Warning("deprecated: goctl rpc template -o is deprecated and will be removed in the future, use goctl rpc -o instead") - - if c.NumFlags() == 0 { - cli.ShowCommandHelpAndExit(c, "template", 1) - } - - protoFile := c.String("o") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") + protoFile := VarStringOutput + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch if len(remote) > 0 { repo, _ := util.CloneIntoGitHome(remote, branch) if len(repo) > 0 { diff --git a/tools/goctl/rpc/cli/zrpc.go b/tools/goctl/rpc/cli/zrpc.go index c99c454bf451..8610b4a5ba0c 100644 --- a/tools/goctl/rpc/cli/zrpc.go +++ b/tools/goctl/rpc/cli/zrpc.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/rpc/generator" "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" @@ -16,37 +16,26 @@ var ( errInvalidGrpcOutput = errors.New("ZRPC: missing --go-grpc_out") errInvalidGoOutput = errors.New("ZRPC: missing --go_out") errInvalidZrpcOutput = errors.New("ZRPC: missing zrpc output, please use --zrpc_out to specify the output") - errInvalidInput = errors.New("ZRPC: missing source") - errMultiInput = errors.New("ZRPC: only one source is expected") ) // ZRPC generates grpc code directly by protoc and generates // zrpc code by goctl. -func ZRPC(c *cli.Context) error { - if c.NumFlags() == 0 { - cli.ShowCommandHelpAndExit(c, "protoc", 1) - } - - args := c.Parent().Args() - protocArgs := removeGoctlFlag(args) +func ZRPC(cmd *cobra.Command, args []string) error { + protocArgs := wrapProtocCmd("protoc", args) pwd, err := os.Getwd() if err != nil { return err } - source, err := getSourceProto(c.Args(), pwd) - if err != nil { - return err - } - - grpcOutList := c.StringSlice("go-grpc_out") - goOutList := c.StringSlice("go_out") - zrpcOut := c.String("zrpc_out") - style := c.String("style") - home := c.String("home") - remote := c.String("remote") - branch := c.String("branch") - verbose := c.Bool("verbose") + source := args[0] + grpcOutList := VarStringSliceGoGRPCOut + goOutList := VarStringSliceGoOut + zrpcOut := VarStringZRPCOut + style := VarStringStyle + home := VarStringHome + remote := VarStringRemote + branch := VarStringBranch + verbose := VarBoolVerbose if len(grpcOutList) == 0 { return errInvalidGrpcOutput } @@ -116,64 +105,25 @@ func ZRPC(c *cli.Context) error { return g.Generate(&ctx) } -func removeGoctlFlag(args []string) []string { - var ret []string - var step int - for step < len(args) { - arg := args[step] - switch { - case arg == "--style", arg == "--home", - arg == "--zrpc_out", arg == "--verbose", - arg == "-v", arg == "--remote", - arg == "--branch": - step += 2 - continue - case strings.HasPrefix(arg, "--style="), - strings.HasPrefix(arg, "--home="), - strings.HasPrefix(arg, "--verbose="), - strings.HasPrefix(arg, "-v="), - strings.HasPrefix(arg, "--remote="), - strings.HasPrefix(arg, "--branch="), - strings.HasPrefix(arg, "--zrpc_out="): - step += 1 - continue - } - step += 1 - ret = append(ret, arg) +func wrapProtocCmd(name string, args []string) []string { + ret := append([]string{name}, args...) + for _, protoPath := range VarStringSliceProtoPath { + ret = append(ret, "--proto_path", protoPath) } - - return ret -} - -func getSourceProto(args []string, pwd string) (string, error) { - var source []string - for _, p := range args { - if strings.HasSuffix(p, ".proto") { - source = append(source, p) - } + for _, goOpt := range VarStringSliceGoOpt { + ret = append(ret, "--go_opt", goOpt) } - - switch len(source) { - case 0: - return "", errInvalidInput - case 1: - isAbs := filepath.IsAbs(source[0]) - if isAbs { - return source[0], nil - } - - abs := filepath.Join(pwd, source[0]) - return abs, nil - default: - return "", errMultiInput + for _, goGRPCOpt := range VarStringSliceGoGRPCOpt { + ret = append(ret, "--go-grpc_opt", goGRPCOpt) } -} - -func removePluginFlag(goOut string) string { - goOut = strings.ReplaceAll(goOut, "plugins=", "") - index := strings.LastIndex(goOut, ":") - if index < 0 { - return goOut + for _, goOut := range VarStringSliceGoOut { + ret = append(ret, "--go_out", goOut) + } + for _, goGRPCOut := range VarStringSliceGoGRPCOut { + ret = append(ret, "--go-grpc_out", goGRPCOut) } - return goOut[index+1:] + for _, plugin := range VarStringSlicePlugin { + ret = append(ret, "--plugin="+plugin) + } + return ret } diff --git a/tools/goctl/rpc/cli/zrpc_test.go b/tools/goctl/rpc/cli/zrpc_test.go deleted file mode 100644 index d841115e5280..000000000000 --- a/tools/goctl/rpc/cli/zrpc_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package cli - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/zeromicro/go-zero/tools/goctl/util/console" -) - -type test struct { - source []string - expected string - expectedErr error -} - -func Test_GetSourceProto(t *testing.T) { - pwd, err := os.Getwd() - if err != nil { - console.Error(err.Error()) - return - } - - testData := []test{ - { - source: []string{"a.proto"}, - expected: filepath.Join(pwd, "a.proto"), - }, - { - source: []string{"/foo/bar/a.proto"}, - expected: "/foo/bar/a.proto", - }, - { - source: []string{"a.proto", "b.proto"}, - expectedErr: errMultiInput, - }, - { - source: []string{"", "--go_out=."}, - expectedErr: errInvalidInput, - }, - } - - for _, d := range testData { - ret, err := getSourceProto(d.source, pwd) - if d.expectedErr != nil { - assert.Equal(t, d.expectedErr, err) - continue - } - - assert.Equal(t, d.expected, ret) - } -} - -func Test_RemoveGoctlFlag(t *testing.T) { - testData := []test{ - { - source: strings.Fields("protoc foo.proto --go_out=. --go_opt=bar --zrpc_out=. --style go-zero --home=foo"), - expected: "protoc foo.proto --go_out=. --go_opt=bar", - }, - { - source: strings.Fields("foo bar foo.proto"), - expected: "foo bar foo.proto", - }, - { - source: strings.Fields("protoc foo.proto --go_out . --style=go_zero --home ."), - expected: "protoc foo.proto --go_out .", - }, - { - source: strings.Fields(`protoc foo.proto --go_out . --style="go_zero" --home="."`), - expected: "protoc foo.proto --go_out .", - }, - { - source: strings.Fields(`protoc foo.proto --go_opt=. --zrpc_out . --style=goZero --home=bar`), - expected: "protoc foo.proto --go_opt=.", - }, - { - source: strings.Fields(`protoc foo.proto --go_opt=. --zrpc_out="bar" --style=goZero --home=bar`), - expected: "protoc foo.proto --go_opt=.", - }, - { - source: strings.Fields(`protoc --go_opt=. --go-grpc_out=. --zrpc_out=. foo.proto`), - expected: "protoc --go_opt=. --go-grpc_out=. foo.proto", - }, - { - source: strings.Fields(`protoc --go_opt=. --go-grpc_out=. --zrpc_out=. --remote=foo --branch=bar foo.proto`), - expected: "protoc --go_opt=. --go-grpc_out=. foo.proto", - }, - { - source: strings.Fields(`protoc --go_opt=. --go-grpc_out=. --zrpc_out=. --remote foo --branch bar foo.proto`), - expected: "protoc --go_opt=. --go-grpc_out=. foo.proto", - }, - } - for _, e := range testData { - cmd := strings.Join(removeGoctlFlag(e.source), " ") - assert.Equal(t, e.expected, cmd) - } -} - -func Test_RemovePluginFlag(t *testing.T) { - testData := []test{ - { - source: strings.Fields("plugins=grpc:."), - expected: ".", - }, - { - source: strings.Fields("plugins=g1,g2:."), - expected: ".", - }, - { - source: strings.Fields("g1,g2:."), - expected: ".", - }, - { - source: strings.Fields("plugins=g1,g2:foo"), - expected: "foo", - }, - } - - for _, e := range testData { - data := removePluginFlag(e.source[0]) - assert.Equal(t, e.expected, data) - } -} diff --git a/tools/goctl/rpc/cmd.go b/tools/goctl/rpc/cmd.go new file mode 100644 index 000000000000..e20538bf5ef0 --- /dev/null +++ b/tools/goctl/rpc/cmd.go @@ -0,0 +1,90 @@ +package rpc + +import ( + "github.com/spf13/cobra" + "github.com/zeromicro/go-zero/tools/goctl/rpc/cli" +) + +var ( + // Cmd describes a rpc command. + Cmd = &cobra.Command{ + Use: "rpc", + Short: "Generate rpc code", + RunE: cli.RPCTemplate, + } + + newCmd = &cobra.Command{ + Use: "new", + Short: "Generate rpc demo service", + Args: cobra.ExactValidArgs(1), + RunE: cli.RPCNew, + } + + templateCmd = &cobra.Command{ + Use: "template", + Short: "Generate proto template", + RunE: cli.RPCTemplate, + } + + protocCmd = &cobra.Command{ + Use: "protoc", + Short: "Generate grpc code", + Example: "goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.", + Args: cobra.ExactValidArgs(1), + RunE: cli.ZRPC, + } +) + +func init() { + Cmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file") + Cmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + Cmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + Cmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "") + newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "") + newCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + newCmd.Flags().BoolVar(&cli.VarBoolIdea, "idea", false, "Whether the command execution environment is from idea plugin.") + newCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority") + newCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo "+ + "directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + newCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it "+ + "does work with --remote") + newCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output") + newCmd.Flags().MarkHidden("go_opt") + newCmd.Flags().MarkHidden("go-grpc_opt") + + protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOut, "go_out", nil, "") + protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out", nil, "") + protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "") + protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "") + protocCmd.Flags().StringSliceVar(&cli.VarStringSlicePlugin, "plugin", nil, "") + protocCmd.Flags().StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I", nil, "") + protocCmd.Flags().StringVar(&cli.VarStringZRPCOut, "zrpc_out", "", "The zrpc output directory") + protocCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]") + protocCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority") + protocCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, "+ + "--home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo "+ + "directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + protocCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it "+ + "does work with --remote") + protocCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output") + protocCmd.Flags().MarkHidden("go_out") + protocCmd.Flags().MarkHidden("go-grpc_out") + protocCmd.Flags().MarkHidden("go_opt") + protocCmd.Flags().MarkHidden("go-grpc_opt") + protocCmd.Flags().MarkHidden("plugin") + protocCmd.Flags().MarkHidden("proto_path") + + templateCmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file") + templateCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority") + templateCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\n\tThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure") + templateCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote") + + Cmd.AddCommand(newCmd) + Cmd.AddCommand(protocCmd) + Cmd.AddCommand(templateCmd) +} diff --git a/tools/goctl/rpc/generator/template.go b/tools/goctl/rpc/generator/template.go index c703406b6306..35fcc83c5bb1 100644 --- a/tools/goctl/rpc/generator/template.go +++ b/tools/goctl/rpc/generator/template.go @@ -3,7 +3,6 @@ package generator import ( "fmt" - "github.com/urfave/cli" "github.com/zeromicro/go-zero/tools/goctl/util/pathx" ) @@ -40,7 +39,7 @@ var templates = map[string]string{ // GenTemplates is the entry for command goctl template, // it will create the specified category -func GenTemplates(_ *cli.Context) error { +func GenTemplates() error { return pathx.InitTemplates(category, templates) } diff --git a/tools/goctl/tpl/cmd.go b/tools/goctl/tpl/cmd.go new file mode 100644 index 000000000000..a6058830d364 --- /dev/null +++ b/tools/goctl/tpl/cmd.go @@ -0,0 +1,55 @@ +package tpl + +import ( + "github.com/spf13/cobra" +) + +var ( + varStringHome string + varStringCategory string + varStringName string + // Cmd describes a template command. + Cmd = &cobra.Command{ + Use: "template", + Short: "Template operation", + } + + initCmd = &cobra.Command{ + Use: "init", + Short: "Initialize the all templates(force update)", + RunE: genTemplates, + } + + cleanCmd = &cobra.Command{ + Use: "clean", + Short: "Clean the all cache templates", + RunE: cleanTemplates, + } + + updateCmd = &cobra.Command{ + Use: "update", + Short: "Update template of the target category to the latest", + RunE: updateTemplates, + } + + revertCmd = &cobra.Command{ + Use: "revert", + Short: "Revert the target template to the latest", + RunE: revertTemplates, + } +) + +func init() { + initCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") + cleanCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") + updateCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") + updateCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]") + revertCmd.Flags().StringVar(&varStringHome, "home", "", "The goctl home path of the template") + revertCmd.Flags().StringVarP(&varStringCategory, "category", "c", "", "The category of template, enum [api,rpc,model,docker,kube]") + revertCmd.Flags().StringVarP(&varStringName, "name", "n", "", "The target file name of template") + + Cmd.AddCommand(cleanCmd) + Cmd.AddCommand(initCmd) + Cmd.AddCommand(revertCmd) + Cmd.AddCommand(updateCmd) +} diff --git a/tools/goctl/tpl/templates.go b/tools/goctl/tpl/templates.go index e6127180a0f8..3cfd89affbb5 100644 --- a/tools/goctl/tpl/templates.go +++ b/tools/goctl/tpl/templates.go @@ -5,7 +5,7 @@ import ( "path/filepath" "github.com/logrusorgru/aurora" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/core/errorx" "github.com/zeromicro/go-zero/tools/goctl/api/apigen" "github.com/zeromicro/go-zero/tools/goctl/api/gogen" @@ -20,37 +20,37 @@ import ( const templateParentPath = "/" -// GenTemplates writes the latest template text into file which is not exists -func GenTemplates(ctx *cli.Context) error { - path := ctx.String("home") +// genTemplates writes the latest template text into file which is not exists +func genTemplates(_ *cobra.Command, _ []string) error { + path := varStringHome if len(path) != 0 { pathx.RegisterGoctlHome(path) } if err := errorx.Chain( func() error { - return gogen.GenTemplates(ctx) + return gogen.GenTemplates() }, func() error { - return modelgen.GenTemplates(ctx) + return modelgen.GenTemplates() }, func() error { - return rpcgen.GenTemplates(ctx) + return rpcgen.GenTemplates() }, func() error { - return docker.GenTemplates(ctx) + return docker.GenTemplates() }, func() error { - return kube.GenTemplates(ctx) + return kube.GenTemplates() }, func() error { - return mongogen.Templates(ctx) + return mongogen.Templates() }, func() error { - return apigen.GenTemplates(ctx) + return apigen.GenTemplates() }, func() error { - return apinew.GenTemplates(ctx) + return apinew.GenTemplates() }, ); err != nil { return err @@ -72,9 +72,9 @@ func GenTemplates(ctx *cli.Context) error { return nil } -// CleanTemplates deletes all templates -func CleanTemplates(ctx *cli.Context) error { - path := ctx.String("home") +// cleanTemplates deletes all templates +func cleanTemplates(_ *cobra.Command, _ []string) error { + path := varStringHome if len(path) != 0 { pathx.RegisterGoctlHome(path) } @@ -113,11 +113,11 @@ func CleanTemplates(ctx *cli.Context) error { return nil } -// UpdateTemplates writes the latest template text into file, +// updateTemplates writes the latest template text into file, // it will delete the older templates if there are exists -func UpdateTemplates(ctx *cli.Context) (err error) { - path := ctx.String("home") - category := ctx.String("category") +func updateTemplates(_ *cobra.Command, _ []string) (err error) { + path := varStringHome + category := varStringCategory if len(path) != 0 { pathx.RegisterGoctlHome(path) } @@ -150,11 +150,11 @@ func UpdateTemplates(ctx *cli.Context) (err error) { } } -// RevertTemplates will overwrite the old template content with the new template -func RevertTemplates(ctx *cli.Context) (err error) { - path := ctx.String("home") - category := ctx.String("category") - filename := ctx.String("name") +// revertTemplates will overwrite the old template content with the new template +func revertTemplates(_ *cobra.Command, _ []string) (err error) { + path := varStringHome + category := varStringCategory + filename := varStringName if len(path) != 0 { pathx.RegisterGoctlHome(path) } diff --git a/tools/goctl/upgrade/cmd.go b/tools/goctl/upgrade/cmd.go new file mode 100644 index 000000000000..73466817692c --- /dev/null +++ b/tools/goctl/upgrade/cmd.go @@ -0,0 +1,10 @@ +package upgrade + +import "github.com/spf13/cobra" + +// Cmd describes a upgrade command. +var Cmd = &cobra.Command{ + Use: "upgrade", + Short: "Upgrade goctl to latest version", + RunE: upgrade, +} diff --git a/tools/goctl/upgrade/upgrade.go b/tools/goctl/upgrade/upgrade.go index d8dac0d8e9d9..1f373cfb110e 100644 --- a/tools/goctl/upgrade/upgrade.go +++ b/tools/goctl/upgrade/upgrade.go @@ -4,13 +4,13 @@ import ( "fmt" "runtime" - "github.com/urfave/cli" + "github.com/spf13/cobra" "github.com/zeromicro/go-zero/tools/goctl/rpc/execx" ) // Upgrade gets the latest goctl by // go install github.com/zeromicro/go-zero/tools/goctl@latest -func Upgrade(_ *cli.Context) error { +func upgrade(_ *cobra.Command, _ []string) error { cmd := `GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest` if runtime.GOOS == "windows" { cmd = `set GOPROXY=https://goproxy.cn,direct && go install github.com/zeromicro/go-zero/tools/goctl@latest` diff --git a/tools/goctl/util/pathx/file.go b/tools/goctl/util/pathx/file.go index 5858ec5157f2..8049e0ac4d0f 100644 --- a/tools/goctl/util/pathx/file.go +++ b/tools/goctl/util/pathx/file.go @@ -2,6 +2,8 @@ package pathx import ( "bufio" + "crypto/md5" + "encoding/hex" "fmt" "io" "io/ioutil" @@ -283,3 +285,19 @@ func Copy(src, dest string) error { _, err = io.Copy(w, f) return err } + +func Hash(file string) (string, error) { + f, err := os.Open(file) + if err != nil { + return "", err + } + defer func() { + _ = f.Close() + }() + hash := md5.New() + _, err = io.Copy(hash, f) + if err != nil { + return "", err + } + return hex.EncodeToString(hash.Sum(nil)), nil +}