Stop special casing runnable root commands

The special case code to handle a runnable root command had some
problems.  It was noticed that if you created a runnable root and a
subcommand.  And the subcommand was then executed with both a valid and
invalid flag, the error message was about the valid flag being invalid.
For example

./command subcommand --goodflag=10 --badflag=10

Would fail and tell you that --goodflag was an invalid flag. Instead if
we just do away with the special Command.execute() for the root command
the parser for subcommand is what prints the error and it gets it
right...
This commit is contained in:
Eric Paris 2015-03-28 23:56:22 -04:00
parent fe581720ad
commit bd0f8a846e

View file

@ -305,6 +305,8 @@ func stripFlags(args []string, c *Command) []string {
inFlag = true inFlag = true
case inFlag: case inFlag:
inFlag = false inFlag = false
case y == "":
// strip empty commands, as the go tests expect this to be ok....
case !strings.HasPrefix(y, "-"): case !strings.HasPrefix(y, "-"):
commands = append(commands, y) commands = append(commands, y)
inFlag = false inFlag = false
@ -375,9 +377,8 @@ func (c *Command) Find(arrs []string) (*Command, []string, error) {
commandFound, a := innerfind(c, arrs) commandFound, a := innerfind(c, arrs)
// if commander returned and the first argument (if it exists) doesn't // If we matched on the root, but we asked for a subcommand, return an error
// match the command name, return nil & error if commandFound.Name() == c.Name() && len(stripFlags(arrs, c)) > 0 && commandFound.Name() != arrs[0] {
if commandFound.Name() == c.Name() && len(arrs[0]) > 0 && commandFound.Name() != arrs[0] {
return nil, a, fmt.Errorf("unknown command %q", a[0]) return nil, a, fmt.Errorf("unknown command %q", a[0])
} }
@ -398,16 +399,6 @@ func (c *Command) Root() *Command {
return findRoot(c) return findRoot(c)
} }
// execute the command determined by args and the command tree
func (c *Command) findAndExecute(args []string) (err error) {
cmd, a, e := c.Find(args)
if e != nil {
return e
}
return cmd.execute(a)
}
func (c *Command) execute(a []string) (err error) { func (c *Command) execute(a []string) (err error) {
if c == nil { if c == nil {
return fmt.Errorf("Called Execute() on a nil Command") return fmt.Errorf("Called Execute() on a nil Command")
@ -494,45 +485,11 @@ func (c *Command) Execute() (err error) {
c.Help() c.Help()
} }
} else { } else {
err = c.findAndExecute(args) cmd, flags, e := c.Find(args)
}
// Now handle the case where the root is runnable and only flags are provided
if err != nil && c.Runnable() {
// This is pretty much a custom version of the *Command.execute method
// with a few differences because it's the final command (no fall back)
e := c.ParseFlags(args)
if e != nil { if e != nil {
// Flags parsing had an error.
// If an error happens here, we have to report it to the user
c.Println(e.Error())
// If an error happens search also for subcommand info about that
if c.cmdErrorBuf != nil && c.cmdErrorBuf.Len() > 0 {
c.Println(c.cmdErrorBuf.String())
} else {
c.Usage()
}
err = e err = e
return
} else { } else {
// If help is called, regardless of other flags, we print that err = cmd.execute(flags)
if c.helpFlagVal {
c.Help()
return nil
}
argWoFlags := c.Flags().Args()
if len(argWoFlags) > 0 {
// If there are arguments (not flags) one of the earlier
// cases should have caught it.. It means invalid usage
// print the usage
c.Usage()
} else {
// Only flags left... Call root.Run
c.preRun()
c.Run(c, argWoFlags)
err = nil
}
} }
} }