feat: 增加命令行工具的参数支持,包括路径、干运行模式和输出目录选项

This commit is contained in:
Rogee
2025-09-10 14:38:53 +08:00
parent 3b804b83da
commit 7187205143
7 changed files with 174 additions and 104 deletions

View File

@@ -9,16 +9,21 @@ import (
)
func CommandBuf(root *cobra.Command) {
cmd := &cobra.Command{
Use: "buf",
Short: "run buf commands",
RunE: commandBufE,
}
cmd := &cobra.Command{
Use: "buf",
Short: "run buf commands",
RunE: commandBufE,
}
cmd.Flags().String("dir", ".", "Directory to run buf from")
cmd.Flags().Bool("dry-run", false, "Preview buf command without executing")
root.AddCommand(cmd)
}
func commandBufE(cmd *cobra.Command, args []string) error {
dir := cmd.Flag("dir").Value.String()
dryRun, _ := cmd.Flags().GetBool("dry-run")
if _, err := exec.LookPath("buf"); err != nil {
log.Warn("buf 命令不存在,正在安装 buf...")
log.Info("go install github.com/bufbuild/buf/cmd/buf@v1.48.0")
@@ -33,9 +38,19 @@ func commandBufE(cmd *cobra.Command, args []string) error {
}
}
log.Info("buf 命令已存在,正在运行 buf generate...")
log.Info("PROTOBUF GUIDE: https://buf.build/docs/best-practices/style-guide/")
generateCmd := exec.Command("buf", "generate")
// preflight: ensure buf.yaml exists
if _, err := os.Stat(filepath.Join(dir, "buf.yaml")); err != nil {
log.Warnf("未找到 %sbuf generate 可能失败", filepath.Join(dir, "buf.yaml"))
}
log.Info("buf 命令已存在,正在运行 buf generate...")
log.Info("PROTOBUF GUIDE: https://buf.build/docs/best-practices/style-guide/")
if dryRun {
log.Infof("[dry-run] (cd %s && buf generate)", dir)
return nil
}
generateCmd := exec.Command("buf", "generate")
generateCmd.Dir = dir
if err := generateCmd.Run(); err != nil {
return fmt.Errorf("运行 buf generate 失败: %v", err)
}

View File

@@ -10,17 +10,20 @@ import (
)
func CommandFmt(root *cobra.Command) {
cmd := &cobra.Command{
Use: "fmt",
Short: "fmt codes",
RunE: commandFmtE,
}
cmd := &cobra.Command{
Use: "fmt",
Short: "fmt codes",
RunE: commandFmtE,
}
cmd.Flags().Bool("check", false, "Check formatting without writing changes")
cmd.Flags().String("path", ".", "Path to format (default .)")
root.AddCommand(cmd)
}
func commandFmtE(cmd *cobra.Command, args []string) error {
log.Info("开始格式化代码")
log.Info("开始格式化代码")
if _, err := exec.LookPath("gofumpt"); err != nil {
log.Info("gofumpt 不存在,正在安装...")
installCmd := exec.Command("go", "install", "mvdan.cc/gofumpt@latest")
@@ -34,14 +37,31 @@ func commandFmtE(cmd *cobra.Command, args []string) error {
}
}
log.Info("运行 gofumpt...")
gofumptCmd := exec.Command("gofumpt", "-l", "-extra", "-w", ".")
gofumptCmd.Stdout = os.Stdout
gofumptCmd.Stderr = os.Stderr
if err := gofumptCmd.Run(); err != nil {
return fmt.Errorf("运行 gofumpt 失败: %v", err)
}
check, _ := cmd.Flags().GetBool("check")
path, _ := cmd.Flags().GetString("path")
log.Info("格式化代码完成")
return nil
if check {
log.Info("运行 gofumpt 检查模式...")
out, err := exec.Command("gofumpt", "-l", "-extra", path).CombinedOutput()
if err != nil {
return fmt.Errorf("运行 gofumpt 失败: %v", err)
}
if len(out) > 0 {
fmt.Fprintln(os.Stdout, string(out))
return fmt.Errorf("发现未格式化文件,请运行: gofumpt -l -extra -w %s", path)
}
log.Info("代码格式良好")
return nil
}
log.Info("运行 gofumpt...")
gofumptCmd := exec.Command("gofumpt", "-l", "-extra", "-w", path)
gofumptCmd.Stdout = os.Stdout
gofumptCmd.Stderr = os.Stderr
if err := gofumptCmd.Run(); err != nil {
return fmt.Errorf("运行 gofumpt 失败: %v", err)
}
log.Info("格式化代码完成")
return nil
}

View File

@@ -25,12 +25,16 @@ import (
)
func CommandGenModel(root *cobra.Command) {
cmd := &cobra.Command{
Use: "model",
Aliases: []string{"m"},
Short: "Generate jet models",
RunE: commandGenModelE,
}
cmd := &cobra.Command{
Use: "model",
Aliases: []string{"m"},
Short: "Generate jet models",
RunE: commandGenModelE,
}
cmd.Flags().String("schema", "", "Override database schema")
cmd.Flags().Bool("rename-schemas", true, "Rename generated database/<db> to database/schemas")
cmd.Flags().String("schemas-out", "database/schemas", "Schemas output directory when renaming")
root.AddCommand(cmd)
}
@@ -40,10 +44,15 @@ func commandGenModelE(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "parse go.mod")
}
_, dbConf, err := pgDatabase.GetDB(cmd.Flag("config").Value.String())
if err != nil {
return errors.Wrap(err, "get db")
}
_, dbConf, err := pgDatabase.GetDB(cmd.Flag("config").Value.String())
if err != nil {
return errors.Wrap(err, "get db")
}
// optional schema override
if s := cmd.Flag("schema").Value.String(); s != "" {
dbConf.Schema = s
}
v := viper.New()
v.SetConfigType("yaml")
@@ -166,14 +175,16 @@ func commandGenModelE(cmd *cobra.Command, args []string) error {
return err
}
if err := os.RemoveAll("database/schemas"); err != nil {
return err
}
dataPath := fmt.Sprintf("database/%s", cfg.Database)
if err := os.Rename(dataPath, "database/schemas"); err != nil {
return err
}
if rename, _ := cmd.Flags().GetBool("rename-schemas"); rename {
out := cmd.Flag("schemas-out").Value.String()
if err := os.RemoveAll(out); err != nil {
return err
}
dataPath := fmt.Sprintf("database/%s", cfg.Database)
if err := os.Rename(dataPath, out); err != nil {
return err
}
}
if err := astModel.Generate(generatedTables, transformer); err != nil {
return err

View File

@@ -1,6 +1,7 @@
package cmd
import (
"fmt"
"io/fs"
"os"
"path/filepath"
@@ -14,28 +15,35 @@ import (
)
func CommandGenRoute(root *cobra.Command) {
cmd := &cobra.Command{
Use: "route",
Short: "generate routes",
RunE: commandGenRouteE,
PostRunE: commandGenProviderE,
}
cmd := &cobra.Command{
Use: "route",
Short: "generate routes",
RunE: commandGenRouteE,
PostRunE: commandGenProviderE,
}
root.AddCommand(cmd)
cmd.Flags().String("path", ".", "Base path to scan (defaults to CWD)")
root.AddCommand(cmd)
}
// https://go.ipao.vip/atomctl/pkg/swag?tab=readme-ov-file#api-operation
func commandGenRouteE(cmd *cobra.Command, args []string) error {
var err error
var path string
if len(args) > 0 {
path = args[0]
} else {
path, err = os.Getwd()
if err != nil {
return err
}
}
var err error
var path string
if len(args) > 0 {
path = args[0]
} else {
path, err = os.Getwd()
if err != nil {
return err
}
}
// allow overriding via --path flag
if f := cmd.Flag("path"); f != nil && f.Value.String() != "." && f.Value.String() != "" {
path = f.Value.String()
}
path, _ = filepath.Abs(path)

View File

@@ -13,12 +13,14 @@ import (
// migrate
func CommandMigrate(root *cobra.Command) {
cmd := &cobra.Command{
Use: "migrate [up|up-by-one|up-to|create|down|down-to|fix|redo|reset|status|version]",
Aliases: []string{"m"},
RunE: commandMigrate,
}
cmd.Flags().StringP("config", "c", "config.toml", "database config file")
cmd := &cobra.Command{
Use: "migrate [up|up-by-one|up-to|create|down|down-to|fix|redo|reset|status|version]",
Aliases: []string{"m"},
RunE: commandMigrate,
}
cmd.Flags().StringP("config", "c", "config.toml", "database config file")
cmd.Flags().String("dir", "database/migrations", "migrations directory")
cmd.Flags().String("table", "migrations", "migrations table name")
root.AddCommand(cmd)
}
@@ -39,10 +41,13 @@ func commandMigrate(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "get db")
}
action, args := args[0], args[1:]
log.Infof("migration action: %s args: %+v", action, args)
action, args := args[0], args[1:]
log.Infof("migration action: %s args: %+v", action, args)
goose.SetTableName("migrations")
dir := cmd.Flag("dir").Value.String()
table := cmd.Flag("table").Value.String()
return goose.RunContext(context.Background(), action, db, "database/migrations", args...)
goose.SetTableName(table)
return goose.RunContext(context.Background(), action, db, dir, args...)
}

View File

@@ -6,20 +6,25 @@ import (
)
func CommandSwagFmt(root *cobra.Command) {
cmd := &cobra.Command{
Use: "fmt",
Aliases: []string{"f"},
Short: "swag format",
RunE: commandSwagFmtE,
}
cmd := &cobra.Command{
Use: "fmt",
Aliases: []string{"f"},
Short: "swag format",
RunE: commandSwagFmtE,
}
cmd.Flags().String("dir", "./app/http", "SearchDir for swag format")
cmd.Flags().String("main", "main.go", "MainFile for swag format")
root.AddCommand(cmd)
}
func commandSwagFmtE(cmd *cobra.Command, args []string) error {
return format.New().Build(&format.Config{
SearchDir: "./app/http",
Excludes: "",
MainFile: "main.go",
})
dir := cmd.Flag("dir").Value.String()
main := cmd.Flag("main").Value.String()
return format.New().Build(&format.Config{
SearchDir: dir,
Excludes: "",
MainFile: main,
})
}

View File

@@ -11,39 +11,45 @@ import (
)
func CommandSwagInit(root *cobra.Command) {
cmd := &cobra.Command{
Use: "init",
Short: "swag init",
Aliases: []string{"i"},
RunE: commandSwagInitE,
}
cmd := &cobra.Command{
Use: "init",
Short: "swag init",
Aliases: []string{"i"},
RunE: commandSwagInitE,
}
cmd.Flags().String("dir", ".", "SearchDir (project root)")
cmd.Flags().String("out", "docs", "Output dir for generated docs")
cmd.Flags().String("main", "main.go", "Main API file path")
root.AddCommand(cmd)
}
func commandSwagInitE(cmd *cobra.Command, args []string) error {
pwd, err := os.Getwd()
if err != nil {
return err
}
if len(args) > 0 {
pwd = args[0]
}
root := cmd.Flag("dir").Value.String()
if root == "" {
var err error
root, err = os.Getwd()
if err != nil { return err }
}
leftDelim, rightDelim := "{{", "}}"
return gen.New().Build(&gen.Config{
SearchDir: pwd,
Excludes: "",
ParseExtension: "",
MainAPIFile: "main.go",
PropNamingStrategy: swag.CamelCase,
OutputDir: filepath.Join(pwd, "docs"),
OutputTypes: []string{"go", "json", "yaml"},
ParseVendor: false,
ParseDependency: 0,
MarkdownFilesDir: "",
ParseInternal: false,
outDir := cmd.Flag("out").Value.String()
mainFile := cmd.Flag("main").Value.String()
return gen.New().Build(&gen.Config{
SearchDir: root,
Excludes: "",
ParseExtension: "",
MainAPIFile: mainFile,
PropNamingStrategy: swag.CamelCase,
OutputDir: filepath.Join(root, outDir),
OutputTypes: []string{"go", "json", "yaml"},
ParseVendor: false,
ParseDependency: 0,
MarkdownFilesDir: "",
ParseInternal: false,
Strict: false,
GeneratedTime: false,
RequiredByDefault: false,