R4R: Support "unknown commands" for subcommands (#4465)
Fixes #4284 Now prints: gaiacli query distr comission --trust-node cosmos1234 ERROR: unknown command "comission" for "distr" Did you mean this? commission Adds custom argument validation for subcommands with subcommands. Doesn't affect "query" or "tx" subcommands since they reside in gaia repo. All flags except help are disabled for these commands.
This commit is contained in:
parent
75de63ce31
commit
6e2f5f3102
|
@ -0,0 +1 @@
|
|||
#4465 Unknown subcommands print relevant error message
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/common"
|
||||
|
@ -352,3 +353,33 @@ func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidateCmd returns unknown command error or Help display if help flag set
|
||||
func ValidateCmd(cmd *cobra.Command, args []string) error {
|
||||
var cmds []string
|
||||
var help bool
|
||||
|
||||
// construct array of commands and search for help flag
|
||||
for _, arg := range args {
|
||||
if arg == "--help" || arg == "-h" {
|
||||
help = true
|
||||
} else if len(arg) > 0 && !(arg[0] == '-') {
|
||||
cmds = append(cmds, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if !help && len(cmds) > 0 {
|
||||
err := fmt.Sprintf("unknown command \"%s\" for \"%s\"", cmds[0], cmd.CalledAs())
|
||||
|
||||
// build suggestions for unknown argument
|
||||
if suggestions := cmd.SuggestionsFor(cmds[0]); len(suggestions) > 0 {
|
||||
err += "\n\nDid you mean this?\n"
|
||||
for _, s := range suggestions {
|
||||
err += fmt.Sprintf("\t%v\n", s)
|
||||
}
|
||||
}
|
||||
return errors.New(err)
|
||||
}
|
||||
|
||||
return cmd.Help()
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
|
@ -112,6 +113,47 @@ func TestReadStdTxFromFile(t *testing.T) {
|
|||
require.Equal(t, decodedTx.Memo, "foomemo")
|
||||
}
|
||||
|
||||
func TestValidateCmd(t *testing.T) {
|
||||
// Setup root and subcommands
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "root",
|
||||
}
|
||||
queryCmd := &cobra.Command{
|
||||
Use: "query",
|
||||
}
|
||||
rootCmd.AddCommand(queryCmd)
|
||||
|
||||
// Command being tested
|
||||
distCmd := &cobra.Command{
|
||||
Use: "distr",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
}
|
||||
queryCmd.AddCommand(distCmd)
|
||||
|
||||
commissionCmd := &cobra.Command{
|
||||
Use: "commission",
|
||||
}
|
||||
distCmd.AddCommand(commissionCmd)
|
||||
|
||||
tests := []struct {
|
||||
reason string
|
||||
args []string
|
||||
wantErr bool
|
||||
}{
|
||||
{"misspelled command", []string{"comission"}, true},
|
||||
{"no command provided", []string{}, false},
|
||||
{"help flag", []string{"comission", "--help"}, false},
|
||||
{"shorthand help flag", []string{"comission", "-h"}, false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
err := ValidateCmd(distCmd, tt.args)
|
||||
assert.Equal(t, tt.wantErr, err != nil, tt.reason)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// aux functions
|
||||
|
||||
func compareEncoders(t *testing.T, expected sdk.TxEncoder, actual sdk.TxEncoder) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis"
|
||||
"github.com/cosmos/cosmos-sdk/x/crisis/client/cli"
|
||||
)
|
||||
|
@ -31,8 +32,11 @@ func (ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for this module
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
txCmd := &cobra.Command{
|
||||
Use: crisis.ModuleName,
|
||||
Short: "crisis transactions subcommands",
|
||||
Use: crisis.ModuleName,
|
||||
Short: "crisis transactions subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
txCmd.AddCommand(client.PostCommands(
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
dist "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
distCmds "github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
|
||||
)
|
||||
|
||||
|
@ -21,8 +23,11 @@ func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
|
|||
// GetQueryCmd returns the cli query commands for this module
|
||||
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
||||
distQueryCmd := &cobra.Command{
|
||||
Use: "distr",
|
||||
Short: "Querying commands for the distribution module",
|
||||
Use: dist.ModuleName,
|
||||
Short: "Querying commands for the distribution module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
distQueryCmd.AddCommand(client.GetCommands(
|
||||
|
@ -40,8 +45,11 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for this module
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
distTxCmd := &cobra.Command{
|
||||
Use: "distr",
|
||||
Short: "Distribution transactions subcommands",
|
||||
Use: dist.ModuleName,
|
||||
Short: "Distribution transactions subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
distTxCmd.AddCommand(client.PostCommands(
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govCli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
|
||||
)
|
||||
|
@ -28,8 +29,11 @@ func NewModuleClient(storeKey string, cdc *amino.Codec, pcmds ...*cobra.Command)
|
|||
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
||||
// Group gov queries under a subcommand
|
||||
govQueryCmd := &cobra.Command{
|
||||
Use: gov.ModuleName,
|
||||
Short: "Querying commands for the governance module",
|
||||
Use: gov.ModuleName,
|
||||
Short: "Querying commands for the governance module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
govQueryCmd.AddCommand(client.GetCommands(
|
||||
|
@ -50,8 +54,11 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for this module
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
govTxCmd := &cobra.Command{
|
||||
Use: gov.ModuleName,
|
||||
Short: "Governance transactions subcommands",
|
||||
Use: gov.ModuleName,
|
||||
Short: "Governance transactions subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
cmdSubmitProp := govCli.GetCmdSubmitProposal(mc.cdc)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
sdkclient "github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||
"github.com/cosmos/cosmos-sdk/x/mint/client/cli"
|
||||
)
|
||||
|
@ -21,8 +22,11 @@ func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
|
|||
// GetQueryCmd returns the cli query commands for the minting module.
|
||||
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
||||
mintingQueryCmd := &cobra.Command{
|
||||
Use: mint.ModuleName,
|
||||
Short: "Querying commands for the minting module",
|
||||
Use: mint.ModuleName,
|
||||
Short: "Querying commands for the minting module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
mintingQueryCmd.AddCommand(
|
||||
|
@ -39,8 +43,11 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for the minting module.
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
mintTxCmd := &cobra.Command{
|
||||
Use: mint.ModuleName,
|
||||
Short: "Minting transaction subcommands",
|
||||
Use: mint.ModuleName,
|
||||
Short: "Minting transaction subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
return mintTxCmd
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
|
||||
)
|
||||
|
@ -23,8 +24,11 @@ func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
|
|||
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
||||
// Group slashing queries under a subcommand
|
||||
slashingQueryCmd := &cobra.Command{
|
||||
Use: slashing.ModuleName,
|
||||
Short: "Querying commands for the slashing module",
|
||||
Use: slashing.ModuleName,
|
||||
Short: "Querying commands for the slashing module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
slashingQueryCmd.AddCommand(
|
||||
|
@ -41,8 +45,11 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for this module
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
slashingTxCmd := &cobra.Command{
|
||||
Use: slashing.ModuleName,
|
||||
Short: "Slashing transactions subcommands",
|
||||
Use: slashing.ModuleName,
|
||||
Short: "Slashing transactions subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
slashingTxCmd.AddCommand(client.PostCommands(
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
@ -22,8 +23,11 @@ func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
|
|||
// GetQueryCmd returns the cli query commands for this module
|
||||
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
||||
stakingQueryCmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: "Querying commands for the staking module",
|
||||
Use: types.ModuleName,
|
||||
Short: "Querying commands for the staking module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
stakingQueryCmd.AddCommand(client.GetCommands(
|
||||
cli.GetCmdQueryDelegation(mc.storeKey, mc.cdc),
|
||||
|
@ -47,8 +51,11 @@ func (mc ModuleClient) GetQueryCmd() *cobra.Command {
|
|||
// GetTxCmd returns the transaction commands for this module
|
||||
func (mc ModuleClient) GetTxCmd() *cobra.Command {
|
||||
stakingTxCmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: "Staking transaction subcommands",
|
||||
Use: types.ModuleName,
|
||||
Short: "Staking transaction subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: utils.ValidateCmd,
|
||||
}
|
||||
|
||||
stakingTxCmd.AddCommand(client.PostCommands(
|
||||
|
|
Loading…
Reference in New Issue