Merge pull request #399 from codegangsta/exit-nonzero-for-unknown-subcommand
Exit non-zero if a unknown subcommand is given
This commit is contained in:
commit
63ed8b0bde
10
CHANGELOG.md
10
CHANGELOG.md
@ -11,11 +11,15 @@
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
|
- `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
|
- 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
|
- `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
|
## [1.16.0] - 2016-05-02
|
||||||
### Added
|
### Added
|
||||||
|
32
help.go
32
help.go
@ -82,10 +82,10 @@ var helpCommand = Command{
|
|||||||
Action: func(c *Context) error {
|
Action: func(c *Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if args.Present() {
|
if args.Present() {
|
||||||
ShowCommandHelp(c, args.First())
|
return ShowCommandHelp(c, args.First())
|
||||||
} else {
|
|
||||||
ShowAppHelp(c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShowAppHelp(c)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -98,11 +98,10 @@ var helpSubcommand = Command{
|
|||||||
Action: func(c *Context) error {
|
Action: func(c *Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if args.Present() {
|
if args.Present() {
|
||||||
ShowCommandHelp(c, args.First())
|
return ShowCommandHelp(c, args.First())
|
||||||
} else {
|
|
||||||
ShowSubcommandHelp(c)
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return ShowSubcommandHelp(c)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,30 +130,31 @@ func DefaultAppComplete(c *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prints help for the given command
|
// 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
|
// show the subcommand help for a command with subcommands
|
||||||
if command == "" {
|
if command == "" {
|
||||||
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range ctx.App.Commands {
|
for _, c := range ctx.App.Commands {
|
||||||
if c.HasName(command) {
|
if c.HasName(command) {
|
||||||
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.App.CommandNotFound != nil {
|
if ctx.App.CommandNotFound == nil {
|
||||||
ctx.App.CommandNotFound(ctx, command)
|
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
|
||||||
} else {
|
|
||||||
fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.App.CommandNotFound(ctx, command)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints help for the given subcommand
|
// Prints help for the given subcommand
|
||||||
func ShowSubcommandHelp(c *Context) {
|
func ShowSubcommandHelp(c *Context) error {
|
||||||
ShowCommandHelp(c, c.Command.Name)
|
return ShowCommandHelp(c, c.Command.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the version number of the App
|
// Prints the version number of the App
|
||||||
|
57
help_test.go
57
help_test.go
@ -2,6 +2,7 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"flag"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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) {
|
func TestShowAppHelp_HiddenCommand(t *testing.T) {
|
||||||
app := &App{
|
app := &App{
|
||||||
Commands: []Command{
|
Commands: []Command{
|
||||||
|
Loading…
Reference in New Issue
Block a user