Merge pull request #399 from codegangsta/exit-nonzero-for-unknown-subcommand

Exit non-zero if a unknown subcommand is given
main
Dan Buch 8 years ago
commit 63ed8b0bde

@ -11,11 +11,15 @@
### Changed
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
quoted in help text output.
quoted in help text output.
- All flag types now include `(default: {value})` strings following usage when a
default value can be (reasonably) detected.
default value can be (reasonably) detected.
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
with non-slice flag types
with non-slice flag types
- Apps now exit with a code of 3 if an unknown subcommand is specified
(previously they printed "No help topic for...", but still exited 0. This
makes it easier to script around apps built using `cli` since they can trust
that a 0 exit code indicated a successful execution.
## [1.16.0] - 2016-05-02
### Added

@ -82,10 +82,10 @@ var helpCommand = Command{
Action: func(c *Context) error {
args := c.Args()
if args.Present() {
ShowCommandHelp(c, args.First())
} else {
ShowAppHelp(c)
return ShowCommandHelp(c, args.First())
}
ShowAppHelp(c)
return nil
},
}
@ -98,11 +98,10 @@ var helpSubcommand = Command{
Action: func(c *Context) error {
args := c.Args()
if args.Present() {
ShowCommandHelp(c, args.First())
} else {
ShowSubcommandHelp(c)
return ShowCommandHelp(c, args.First())
}
return nil
return ShowSubcommandHelp(c)
},
}
@ -131,30 +130,31 @@ func DefaultAppComplete(c *Context) {
}
// Prints help for the given command
func ShowCommandHelp(ctx *Context, command string) {
func ShowCommandHelp(ctx *Context, command string) error {
// show the subcommand help for a command with subcommands
if command == "" {
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
return
return nil
}
for _, c := range ctx.App.Commands {
if c.HasName(command) {
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
return
return nil
}
}
if ctx.App.CommandNotFound != nil {
ctx.App.CommandNotFound(ctx, command)
} else {
fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command)
if ctx.App.CommandNotFound == nil {
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
}
ctx.App.CommandNotFound(ctx, command)
return nil
}
// Prints help for the given subcommand
func ShowSubcommandHelp(c *Context) {
ShowCommandHelp(c, c.Command.Name)
func ShowSubcommandHelp(c *Context) error {
return ShowCommandHelp(c, c.Command.Name)
}
// Prints the version number of the App

@ -2,6 +2,7 @@ package cli
import (
"bytes"
"flag"
"strings"
"testing"
)
@ -112,6 +113,62 @@ func Test_Version_Custom_Flags(t *testing.T) {
}
}
func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp()
set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"})
c := NewContext(app, set, nil)
err := helpCommand.Action.(func(*Context) error)(c)
if err == nil {
t.Fatalf("expected error from helpCommand.Action(), but got nil")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
}
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
}
if exitErr.exitCode != 3 {
t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
}
}
func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp()
set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"})
c := NewContext(app, set, nil)
err := helpSubcommand.Action.(func(*Context) error)(c)
if err == nil {
t.Fatalf("expected error from helpCommand.Action(), but got nil")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
}
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
}
if exitErr.exitCode != 3 {
t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
}
}
func TestShowAppHelp_HiddenCommand(t *testing.T) {
app := &App{
Commands: []Command{

Loading…
Cancel
Save