Allow for legacy and newer Action func signatures
This commit is contained in:
parent
d48e22a9dd
commit
d45f7c1fe2
51
app.go
51
app.go
@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@ -55,7 +56,10 @@ type App struct {
|
||||
// It is run even if Action() panics
|
||||
After AfterFunc
|
||||
// The action to execute when no subcommands are specified
|
||||
Action ActionFunc
|
||||
Action interface{}
|
||||
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
|
||||
// of deprecation period has passed, maybe?
|
||||
|
||||
// Execute this function if the proper command cannot be found
|
||||
CommandNotFound CommandNotFoundFunc
|
||||
// Execute this function if an usage error occurs
|
||||
@ -179,8 +183,7 @@ func (a *App) Run(arguments []string) (err error) {
|
||||
|
||||
if a.After != nil {
|
||||
defer func() {
|
||||
afterErr := a.After(context)
|
||||
if afterErr != nil {
|
||||
if afterErr := a.After(context); afterErr != nil {
|
||||
if err != nil {
|
||||
err = NewMultiError(err, afterErr)
|
||||
} else {
|
||||
@ -210,9 +213,11 @@ func (a *App) Run(arguments []string) (err error) {
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
err = a.Action(context)
|
||||
HandleExitCoder(err)
|
||||
err = HandleAction(a.Action, context)
|
||||
|
||||
if err != nil {
|
||||
HandleExitCoder(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@ -318,7 +323,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
||||
}
|
||||
|
||||
// Run default Action
|
||||
return a.Action(context)
|
||||
err = HandleAction(a.Action, context)
|
||||
|
||||
if err != nil {
|
||||
HandleExitCoder(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Returns the named command on App. Returns nil if the command does not exist
|
||||
@ -368,3 +378,32 @@ func (a Author) String() string {
|
||||
|
||||
return fmt.Sprintf("%v %v", a.Name, e)
|
||||
}
|
||||
|
||||
// HandleAction uses ✧✧✧reflection✧✧✧ to figure out if the given Action is an
|
||||
// ActionFunc, LegacyActionFunc, or some other invalid thing. If it's an
|
||||
// ActionFunc or LegacyActionFunc, the func is run!
|
||||
func HandleAction(action interface{}, context *Context) error {
|
||||
if reflect.TypeOf(action).Kind() != reflect.Func {
|
||||
panic("given Action must be a func")
|
||||
}
|
||||
|
||||
vals := reflect.ValueOf(action).Call([]reflect.Value{reflect.ValueOf(context)})
|
||||
|
||||
if len(vals) == 0 {
|
||||
fmt.Fprintln(os.Stderr,
|
||||
"DEPRECATED Action signature. Must be `cli.ActionFunc`")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(vals) > 1 {
|
||||
fmt.Fprintln(os.Stderr,
|
||||
"ERROR invalid Action signature. Must be `cli.ActionFunc`")
|
||||
panic("given Action has invalid return signature")
|
||||
}
|
||||
|
||||
if err, ok := reflect.ValueOf(vals[0]).Interface().(error); ok {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -34,7 +34,10 @@ type Command struct {
|
||||
// It is run even if Action() panics
|
||||
After AfterFunc
|
||||
// The function to call when this command is invoked
|
||||
Action ActionFunc
|
||||
Action interface{}
|
||||
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
|
||||
// of deprecation period has passed, maybe?
|
||||
|
||||
// Execute this function if a usage error occurs.
|
||||
OnUsageError OnUsageErrorFunc
|
||||
// List of child commands
|
||||
@ -178,7 +181,8 @@ func (c Command) Run(ctx *Context) (err error) {
|
||||
}
|
||||
|
||||
context.Command = c
|
||||
err = c.Action(context)
|
||||
err = HandleAction(c.Action, context)
|
||||
|
||||
if err != nil {
|
||||
HandleExitCoder(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user