mirror of
https://github.com/spf13/cobra
synced 2024-11-24 14:47:12 +00:00
Return an error in the case of unrunnable subcommand
* credit to @chriswhelix for initial commit
This commit is contained in:
parent
9552679939
commit
9334a46bd6
2 changed files with 16 additions and 4 deletions
16
command.go
16
command.go
|
@ -17,6 +17,7 @@ package cobra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -27,6 +28,9 @@ import (
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NotRunnable defines subcommand error
|
||||||
|
var NotRunnable = errors.New("subcommand is required")
|
||||||
|
|
||||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||||
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
||||||
|
|
||||||
|
@ -369,7 +373,7 @@ func (c *Command) HelpFunc() func(*Command, []string) {
|
||||||
}
|
}
|
||||||
return func(c *Command, a []string) {
|
return func(c *Command, a []string) {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
|
err := tmpl(c.OutOrStderr(), c.HelpTemplate(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Println(err)
|
c.Println(err)
|
||||||
}
|
}
|
||||||
|
@ -786,7 +790,7 @@ func (c *Command) execute(a []string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.Runnable() {
|
if !c.Runnable() {
|
||||||
return flag.ErrHelp
|
return NotRunnable
|
||||||
}
|
}
|
||||||
|
|
||||||
c.preRun()
|
c.preRun()
|
||||||
|
@ -920,6 +924,14 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If command wasn't runnable, show full help, but do return the error.
|
||||||
|
// This will result in apps by default returning a non-success exit code, but also gives them the option to
|
||||||
|
// handle specially.
|
||||||
|
if err == NotRunnable {
|
||||||
|
cmd.HelpFunc()(cmd, args)
|
||||||
|
return cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
// If root command has SilentErrors flagged,
|
// If root command has SilentErrors flagged,
|
||||||
// all subcommands should respect it
|
// all subcommands should respect it
|
||||||
if !cmd.SilenceErrors && !c.SilenceErrors {
|
if !cmd.SilenceErrors && !c.SilenceErrors {
|
||||||
|
|
|
@ -836,8 +836,8 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
|
||||||
rootCmd.AddCommand(childCmd)
|
rootCmd.AddCommand(childCmd)
|
||||||
|
|
||||||
output, err := executeCommand(rootCmd, "child")
|
output, err := executeCommand(rootCmd, "child")
|
||||||
if err != nil {
|
if err != NotRunnable {
|
||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Expected error")
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStringContains(t, output, childCmd.Long)
|
checkStringContains(t, output, childCmd.Long)
|
||||||
|
|
Loading…
Reference in a new issue