Merge pull request #315 from blaubaer/master

Improved Before/After handling for Commands
This commit is contained in:
Jesse Szwedko 2016-01-21 21:44:38 -08:00
commit f9cc3001e0
4 changed files with 59 additions and 3 deletions

3
app.go
View File

@ -164,6 +164,9 @@ func (a *App) Run(arguments []string) (err error) {
if a.Before != nil { if a.Before != nil {
err := a.Before(context) err := a.Before(context)
if err != nil { if err != nil {
fmt.Fprintln(a.Writer, err)
fmt.Fprintln(a.Writer)
ShowAppHelp(context)
return err return err
} }
} }

View File

@ -942,6 +942,11 @@ func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp() app := NewApp()
app.Commands = []Command{ app.Commands = []Command{
Command{ Command{
Subcommands: []Command{
Command{
Name: "sub",
},
},
Name: "bar", Name: "bar",
Before: func(c *Context) error { return fmt.Errorf("before error") }, Before: func(c *Context) error { return fmt.Errorf("before error") },
After: func(c *Context) error { return fmt.Errorf("after error") }, After: func(c *Context) error { return fmt.Errorf("after error") },

View File

@ -54,8 +54,8 @@ func (c Command) FullName() string {
} }
// Invokes the command given the context, parses ctx.Args() to generate command-specific flags // Invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c Command) Run(ctx *Context) error { func (c Command) Run(ctx *Context) (err error) {
if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { if len(c.Subcommands) > 0 {
return c.startApp(ctx) return c.startApp(ctx)
} }
@ -74,7 +74,6 @@ func (c Command) Run(ctx *Context) error {
set := flagSet(c.Name, c.Flags) set := flagSet(c.Name, c.Flags)
set.SetOutput(ioutil.Discard) set.SetOutput(ioutil.Discard)
var err error
if !c.SkipFlagParsing { if !c.SkipFlagParsing {
firstFlagIndex := -1 firstFlagIndex := -1
terminatorIndex := -1 terminatorIndex := -1
@ -133,6 +132,30 @@ func (c Command) Run(ctx *Context) error {
if checkCommandHelp(context, c.Name) { if checkCommandHelp(context, c.Name) {
return nil return nil
} }
if c.After != nil {
defer func() {
afterErr := c.After(context)
if afterErr != nil {
if err != nil {
err = NewMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}
if c.Before != nil {
err := c.Before(context)
if err != nil {
fmt.Fprintln(ctx.App.Writer, err)
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
return err
}
}
context.Command = c context.Command = c
c.Action(context) c.Action(context)
return nil return nil

View File

@ -5,6 +5,8 @@ import (
"flag" "flag"
"io/ioutil" "io/ioutil"
"testing" "testing"
"fmt"
"strings"
) )
func TestCommandFlagParsing(t *testing.T) { func TestCommandFlagParsing(t *testing.T) {
@ -43,3 +45,26 @@ func TestCommandFlagParsing(t *testing.T) {
expect(t, []string(context.Args()), c.testArgs) expect(t, []string(context.Args()), c.testArgs)
} }
} }
func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp()
app.Commands = []Command{
Command{
Name: "bar",
Before: func(c *Context) error { return fmt.Errorf("before error") },
After: func(c *Context) error { return fmt.Errorf("after error") },
},
}
err := app.Run([]string{"foo", "bar"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.Contains(err.Error(), "before error") {
t.Errorf("expected text of error from Before method, but got none in \"%v\"", err)
}
if !strings.Contains(err.Error(), "after error") {
t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
}
}