package cmd import ( "fmt" "os" "runtime" "strings" "github.com/aws-cloudformation/rain/internal/config" "github.com/aws-cloudformation/rain/internal/console" "github.com/aws-cloudformation/rain/internal/console/spinner" "github.com/spf13/cobra" "github.com/spf13/pflag" ) // AddDefaults add standard additional flags and version information to a command func AddDefaults(c *cobra.Command) { // Don't add "[flags]" to the usage line c.DisableFlagsInUseLine = true // Set version string c.Version = config.VERSION // Add the debug flag c.PersistentFlags().BoolVarP(&config.Debug, "debug", "", false, "Output debugging information") // Customise version string if c.Name() == "rain" { c.SetVersionTemplate(fmt.Sprintf("%s {{.Version}} %s/%s\n", config.NAME, runtime.GOOS, runtime.GOARCH, )) } else { c.SetVersionTemplate(fmt.Sprintf("{{.Name}} (%s {{.Version}} %s/%s)\n", config.NAME, runtime.GOOS, runtime.GOARCH, )) } } // Wrap creates a new command with the same functionality as src // but with a new name and default options added for executables // e.g. the --debug flag // The new command is then executed func Wrap(name string, src *cobra.Command) { use := strings.Split(src.Use, " ") use[0] = name // Create the new command out := &cobra.Command{ Use: strings.Join(use, " "), Short: src.Short, Long: src.Long, Args: src.Args, Run: src.Run, } // Set default options AddDefaults(out) // Add the flags src.Flags().VisitAll(func(f *pflag.Flag) { out.Flags().AddFlag(f) }) Execute(out) } func execute(cmd *cobra.Command) (code int) { defer func() { spinner.Stop() if r := recover(); r != nil { if config.Debug { panic(r) } fmt.Fprintln(os.Stderr, console.Red(fmt.Sprint(r))) code = 1 } }() if err := cmd.Execute(); err != nil { code = 1 } return } // Execute wraps a command with error trapping that deals with the debug flag func Execute(cmd *cobra.Command) { os.Exit(execute(cmd)) } // Test runs a command without calling os.Exit and instead returning the error code. // Use this in place of Execute for functional testing func Test(cmd *cobra.Command) int { return execute(cmd) }