Skip to content

Commit

Permalink
Fix Parsing of Nested Subcommands (#9236)
Browse files Browse the repository at this point in the history
(cherry picked from commit 2ffe833)
  • Loading branch information
nisdas authored and prestonvanloon committed Jul 21, 2021
1 parent a9ee3ee commit b365090
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
17 changes: 16 additions & 1 deletion shared/cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,28 @@ func LoadFlagsFromConfig(cliCtx *cli.Context, flags []cli.Flag) error {
// ValidateNoArgs insures that the application is not run with erroneous arguments or flags.
// This function should be used in the app.Before, whenever the application supports a default command.
func ValidateNoArgs(ctx *cli.Context) error {
commandList := ctx.App.Commands
for _, a := range ctx.Args().Slice() {
if strings.HasPrefix(a, "-") {
continue
}
if c := ctx.App.Command(a); c == nil {
c := checkCommandList(commandList, a)
if c == nil {
return fmt.Errorf("unrecognized argument: %s", a)
}
// Set the command list as the subcommand's
// from the current selected parent command.
commandList = c.Subcommands
}
return nil
}

// verifies that the provided command is in the command list.
func checkCommandList(commands []*cli.Command, name string) *cli.Command {
for _, c := range commands {
if c.Name == name {
return c
}
}
return nil
}
53 changes: 53 additions & 0 deletions shared/cmd/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ func TestValidateNoArgs(t *testing.T) {
Commands: []*cli.Command{
{
Name: "bar",
Subcommands: []*cli.Command{
{
Name: "subComm1",
Subcommands: []*cli.Command{
{
Name: "subComm3",
},
},
},
{
Name: "subComm2",
Subcommands: []*cli.Command{
{
Name: "subComm4",
},
},
},
},
},
},
}
Expand All @@ -71,4 +89,39 @@ func TestValidateNoArgs(t *testing.T) {
// It should fail on unregistered flag (default logic in urfave/cli).
err = app.Run([]string{"command", "bar", "--baz"})
require.ErrorContains(t, "flag provided but not defined", err)

// Handle Nested Subcommands

err = app.Run([]string{"command", "bar", "subComm1"})
require.NoError(t, err)

err = app.Run([]string{"command", "bar", "subComm2"})
require.NoError(t, err)

// Should fail from unknown subcommands.
err = app.Run([]string{"command", "bar", "subComm3"})
require.ErrorContains(t, "unrecognized argument: subComm3", err)

err = app.Run([]string{"command", "bar", "subComm4"})
require.ErrorContains(t, "unrecognized argument: subComm4", err)

// Should fail with invalid double nested subcommands.
err = app.Run([]string{"command", "bar", "subComm1", "subComm2"})
require.ErrorContains(t, "unrecognized argument: subComm2", err)

err = app.Run([]string{"command", "bar", "subComm1", "subComm4"})
require.ErrorContains(t, "unrecognized argument: subComm4", err)

err = app.Run([]string{"command", "bar", "subComm2", "subComm1"})
require.ErrorContains(t, "unrecognized argument: subComm1", err)

err = app.Run([]string{"command", "bar", "subComm2", "subComm3"})
require.ErrorContains(t, "unrecognized argument: subComm3", err)

// Should pass with correct nested double subcommands.
err = app.Run([]string{"command", "bar", "subComm1", "subComm3"})
require.NoError(t, err)

err = app.Run([]string{"command", "bar", "subComm2", "subComm4"})
require.NoError(t, err)
}

0 comments on commit b365090

Please sign in to comment.