diff --git a/CHANGELOG.md b/CHANGELOG.md index 79947cba3ce3..10436fa612b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,9 @@ upgrade via: `sudo rm -rf /Library/Developer/CommandLineTools; xcode-select --in correct version via: `pkgutil --pkg-info=com.apple.pkg.CLTools_Executables`. * (keys) [\#5097](https://github.com/cosmos/cosmos-sdk/pull/5097) New `keys migrate` command to assist users migrate their keys to the new keyring. +* (keys) [\#5366](https://github.com/cosmos/cosmos-sdk/pull/5366) `keys list` now accepts a `--list-names` option to list key names only, whilst the `keys delete` +command can delete multiple keys by passing their names as arguments. The aforementioned commands can then be piped together, e.g. +`appcli keys list -n | xargs appcli keys delete` * (modules) [\#4233](https://github.com/cosmos/cosmos-sdk/pull/4233) Add upgrade module that coordinates software upgrades of live chains. * [\#4486](https://github.com/cosmos/cosmos-sdk/issues/4486) Introduce new `PeriodicVestingAccount` vesting account type that allows for arbitrary vesting periods. diff --git a/client/keys/delete.go b/client/keys/delete.go index d2e535105a19..aadc831fe129 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -18,27 +18,26 @@ const ( func deleteKeyCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "delete ", - Short: "Delete the given key", - Long: `Delete a key from the store. + Use: "delete ...", + Short: "Delete the given keys", + Long: `Delete keys from the Keybase backend. Note that removing offline or ledger keys will remove only the public key references stored locally, i.e. private keys stored in a ledger device cannot be deleted with the CLI. `, RunE: runDeleteCmd, - Args: cobra.ExactArgs(1), + Args: cobra.MinimumNArgs(1), } cmd.Flags().BoolP(flagYes, "y", false, "Skip confirmation prompt when deleting offline or ledger key references") cmd.Flags().BoolP(flagForce, "f", false, - "Remove the key unconditionally without asking for the passphrase") + "Remove the key unconditionally without asking for the passphrase. Deprecated.") return cmd } func runDeleteCmd(cmd *cobra.Command, args []string) error { - name := args[0] buf := bufio.NewReader(cmd.InOrStdin()) kb, err := NewKeyringFromHomeFlag(buf) @@ -46,31 +45,34 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { return err } - info, err := kb.Get(name) - if err != nil { - return err - } + for _, name := range args { + info, err := kb.Get(name) + if err != nil { + return err + } - if info.GetType() == keys.TypeLedger || info.GetType() == keys.TypeOffline { - // confirm deletion, unless -y is passed - if !viper.GetBool(flagYes) { - if err := confirmDeletion(buf); err != nil { + if info.GetType() == keys.TypeLedger || info.GetType() == keys.TypeOffline { + // confirm deletion, unless -y is passed + if !viper.GetBool(flagYes) { + if err := confirmDeletion(buf); err != nil { + return err + } + } + + if err := kb.Delete(name, "", true); err != nil { return err } + cmd.PrintErrln("Public key reference deleted") + return nil } + // old password and skip flag arguments are ignored if err := kb.Delete(name, "", true); err != nil { return err } - cmd.PrintErrln("Public key reference deleted") - return nil + cmd.PrintErrln("Key deleted forever (uh oh!)") } - // old password and skip flag arguments are ignored - if err := kb.Delete(name, "", true); err != nil { - return err - } - cmd.PrintErrln("Key deleted forever (uh oh!)") return nil } diff --git a/client/keys/list.go b/client/keys/list.go index da4d4b22240f..45d29a942699 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -2,10 +2,13 @@ package keys import ( "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/flags" ) +const flagListNames = "list-names" + func listKeysCmd() *cobra.Command { cmd := &cobra.Command{ Use: "list", @@ -15,18 +18,30 @@ along with their associated name and address.`, RunE: runListCmd, } cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") + cmd.Flags().BoolP(flagListNames, "n", false, "List names only") return cmd } -func runListCmd(cmd *cobra.Command, args []string) error { +func runListCmd(cmd *cobra.Command, _ []string) error { kb, err := NewKeyringFromHomeFlag(cmd.InOrStdin()) if err != nil { return err } infos, err := kb.List() - if err == nil { + if err != nil { + return err + } + + if !viper.GetBool(flagListNames) { printInfos(infos) + return nil + } + + cmd.SetOut(cmd.OutOrStdout()) + for _, info := range infos { + cmd.Println(info.GetName()) } - return err + + return nil } diff --git a/client/keys/list_test.go b/client/keys/list_test.go index b8cfb223caef..8f4a5b6411b6 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -57,10 +57,19 @@ func Test_runListCmd(t *testing.T) { if runningUnattended { mockIn.Reset("testpass1\ntestpass1\n") } + viper.Set(flagListNames, false) viper.Set(flags.FlagHome, tt.kbDir) if err := runListCmd(tt.args.cmd, tt.args.args); (err != nil) != tt.wantErr { t.Errorf("runListCmd() error = %v, wantErr %v", err, tt.wantErr) } + + if runningUnattended { + mockIn.Reset("testpass1\ntestpass1\n") + } + viper.Set(flagListNames, true) + if err := runListCmd(tt.args.cmd, tt.args.args); (err != nil) != tt.wantErr { + t.Errorf("runListCmd() error = %v, wantErr %v", err, tt.wantErr) + } }) } }