gitlink-cli/shortcuts/common/runner.go

106 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"fmt"
"os"
"strconv"
"github.com/spf13/cobra"
"github.com/gitlink-org/gitlink-cli/cmd/cmdutil"
)
// MountShortcut converts a Shortcut into a cobra.Command and adds it as a subcommand.
func MountShortcut(parent *cobra.Command, s *Shortcut) {
cmd := &cobra.Command{
Use: "+" + s.Name,
Short: s.Description,
RunE: func(cmd *cobra.Command, args []string) error {
// Collect flag values
flagValues := make(map[string]string)
for _, f := range s.Flags {
if f.Bool {
val, _ := cmd.Flags().GetBool(f.Name)
flagValues[f.Name] = strconv.FormatBool(val)
continue
}
val, _ := cmd.Flags().GetString(f.Name)
if val != "" {
flagValues[f.Name] = val
}
}
commandName := parent.Use + " +" + s.Name
ctx, err := NewRuntimeContext(flagValues, commandName)
if err != nil {
return err
}
// Dry-run interception
if s.DryRun {
if dryRunVal, _ := cmd.Flags().GetBool("dry-run"); dryRunVal {
flagValues["dry-run"] = "true"
if s.DryRunHint != nil {
hint, err := s.DryRunHint(ctx)
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "[dry-run] %s\n", hint)
}
proceed, err := ConfirmAction(ctx)
if err != nil {
return err
}
if !proceed {
return nil
}
}
}
err = s.Run(ctx)
if err != nil {
// 当错误为已识别的 API/CLI 错误时,按 envelope 格式输出到 stdout
// 让 `--format json` 输出可被 jq 解析的标准结构。
// 已识别后返回 ErrSilent保留非零退出码但 cmd.Execute 不会再 stderr 重复输出。
if TryPrintError(err, ctx.Format) {
return cmdutil.ErrSilent
}
}
return err
},
}
for _, f := range s.Flags {
usage := f.Usage
if f.Required {
usage = usage + " [required]"
}
if f.Bool {
defaultValue, _ := strconv.ParseBool(f.Default)
if f.Short != "" {
cmd.Flags().BoolP(f.Name, f.Short, defaultValue, usage)
} else {
cmd.Flags().Bool(f.Name, defaultValue, usage)
}
} else if f.Short != "" {
cmd.Flags().StringP(f.Name, f.Short, f.Default, usage)
} else {
cmd.Flags().String(f.Name, f.Default, usage)
}
}
// Auto-register --dry-run flag for shortcuts that support it
if s.DryRun {
cmd.Flags().Bool("dry-run", false, "Preview the operation without executing")
}
parent.AddCommand(cmd)
}
// MountShortcuts mounts multiple shortcuts under a parent command.
func MountShortcuts(parent *cobra.Command, shortcuts []*Shortcut) {
for _, s := range shortcuts {
MountShortcut(parent, s)
}
}