Skip to content

Commit

Permalink
Aggregate errors from Before/After
Browse files Browse the repository at this point in the history
Previously `After` would overwrite any error from `Before`.
  • Loading branch information
jszwedko committed Jun 2, 2015
1 parent 5d58d5b commit 7ed7a51
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 8 deletions.
24 changes: 16 additions & 8 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,14 @@ func (a *App) Run(arguments []string) (err error) {

if a.After != nil {
defer func() {
// err is always nil here.
// There is a check to see if it is non-nil
// just few lines before.
err = a.After(context)
afterErr := a.After(context)
if afterErr != nil {
if err != nil {
err = NewMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}

Expand Down Expand Up @@ -225,10 +229,14 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {

if a.After != nil {
defer func() {
// err is always nil here.
// There is a check to see if it is non-nil
// just few lines before.
err = a.After(context)
afterErr := a.After(context)
if afterErr != nil {
if err != nil {
err = NewMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}

Expand Down
42 changes: 42 additions & 0 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,3 +709,45 @@ func TestApp_Run_CommandWithSubcommandHasHelpTopic(t *testing.T) {
}
}
}

func TestApp_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
app := cli.NewApp()
app.Action = func(c *cli.Context) {}
app.Before = func(c *cli.Context) error { return fmt.Errorf("before error") }
app.After = func(c *cli.Context) error { return fmt.Errorf("after error") }

err := app.Run([]string{"foo"})
if err == nil {
t.Fatalf("expected to recieve 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)
}
}

func TestApp_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) {
app := cli.NewApp()
app.Commands = []cli.Command{
cli.Command{
Name: "bar",
Before: func(c *cli.Context) error { return fmt.Errorf("before error") },
After: func(c *cli.Context) error { return fmt.Errorf("after error") },
},
}

err := app.Run([]string{"foo", "bar"})
if err == nil {
t.Fatalf("expected to recieve 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)
}
}
21 changes: 21 additions & 0 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,24 @@
// app.Run(os.Args)
// }
package cli

import (
"strings"
)

type MultiError struct {
Errors []error
}

func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}

func (m MultiError) Error() string {
errs := make([]string, len(m.Errors))
for i, err := range m.Errors {
errs[i] = err.Error()
}

return strings.Join(errs, "\n")
}

0 comments on commit 7ed7a51

Please sign in to comment.