From 14897ba5875834933be6119f942cf7b5cc17dcbb Mon Sep 17 00:00:00 2001 From: lew Date: Wed, 17 Dec 2025 18:18:48 +0000 Subject: [PATCH] feat(del): support for multi deletion --- README.md | 11 +++++- cmd/del.go | 72 +++++++++++++++++++++-------------- testdata/del__multiple__ok.ct | 7 ++++ testdata/help__del__ok.ct | 8 ++-- testdata/help__ok.ct | 4 +- testdata/root__ok.ct | 2 +- 6 files changed, 66 insertions(+), 38 deletions(-) create mode 100644 testdata/del__multiple__ok.ct diff --git a/README.md b/README.md index 4a7510b..df1bf86 100644 --- a/README.md +++ b/README.md @@ -123,14 +123,21 @@ pda mv name name2 --copy

-`pda del` to delete a key. +`pda del` to delete one or more keys. ```bash pda del kitty -# Are you sure you want to delete kitty? [y/N] +# remove "kitty": are you sure? [y/n] +# y + +pda del kitty dog@animals +# remove "kitty", "dog@animals": are you sure? [y/n] # y # Or skip the prompt. pda del kitty --force + +# Delete many in one go. +pda del kitty dogs cats --force ```

diff --git a/cmd/del.go b/cmd/del.go index ed4625f..852dbf1 100644 --- a/cmd/del.go +++ b/cmd/del.go @@ -32,10 +32,10 @@ import ( // delCmd represents the set command var delCmd = &cobra.Command{ - Use: "del KEY[@DB]", - Short: "Delete a key. Optionally specify a db.", + Use: "del KEY[@DB] [KEY[@DB] ...]", + Short: "Delete one or more keys. Optionally specify a db.", Aliases: []string{"delete", "rm", "remove"}, - Args: cobra.ExactArgs(1), + Args: cobra.MinimumNArgs(1), RunE: del, SilenceUsage: true, } @@ -48,22 +48,29 @@ func del(cmd *cobra.Command, args []string) error { return err } - exists, err := keyExists(store, args[0]) - if err != nil { - return fmt.Errorf("cannot remove '%s': %v", args[0], err) - } - if !exists { - return fmt.Errorf("cannot remove '%s': No such key", args[0]) - } - - targetKey, err := formatKeyForPrompt(store, args[0]) - if err != nil { - return err + targetKeys := make([]string, 0, len(args)) + for _, arg := range args { + exists, err := keyExists(store, arg) + if err != nil { + return fmt.Errorf("cannot remove '%s': %v", arg, err) + } + if !exists { + return fmt.Errorf("cannot remove '%s': No such key", arg) + } + targetKey, err := formatKeyForPrompt(store, arg) + if err != nil { + return err + } + targetKeys = append(targetKeys, targetKey) } if !force { var confirm string - message := fmt.Sprintf("remove %q: are you sure? (y/n)", targetKey) + quotedTargets := make([]string, 0, len(targetKeys)) + for _, t := range targetKeys { + quotedTargets = append(quotedTargets, fmt.Sprintf("%q", t)) + } + message := fmt.Sprintf("remove %s: are you sure? (y/n)", strings.Join(quotedTargets, ", ")) fmt.Println(message) if _, err := fmt.Scanln(&confirm); err != nil { return fmt.Errorf("cannot remove '%s': %v", args[0], err) @@ -73,22 +80,29 @@ func del(cmd *cobra.Command, args []string) error { } } - trans := TransactionArgs{ - key: args[0], - readonly: false, - sync: false, - transact: func(tx *badger.Txn, k []byte) error { - if err := tx.Delete(k); errors.Is(err, badger.ErrKeyNotFound) { - return fmt.Errorf("cannot remove '%s': No such key", args[0]) - } - if err != nil { - return fmt.Errorf("cannot remove '%s': %v", args[0], err) - } - return nil - }, + for _, arg := range args { + arg := arg + trans := TransactionArgs{ + key: arg, + readonly: false, + sync: false, + transact: func(tx *badger.Txn, k []byte) error { + if err := tx.Delete(k); errors.Is(err, badger.ErrKeyNotFound) { + return fmt.Errorf("cannot remove '%s': No such key", arg) + } + if err != nil { + return fmt.Errorf("cannot remove '%s': %v", arg, err) + } + return nil + }, + } + + if err := store.Transaction(trans); err != nil { + return err + } } - return store.Transaction(trans) + return nil } func init() { diff --git a/testdata/del__multiple__ok.ct b/testdata/del__multiple__ok.ct new file mode 100644 index 0000000..2b105c1 --- /dev/null +++ b/testdata/del__multiple__ok.ct @@ -0,0 +1,7 @@ +$ pda set a 1 +$ pda set b 2 +$ pda del a b --force +$ pda get a --> FAIL +Error: cannot get 'a': Key not found +$ pda get b --> FAIL +Error: cannot get 'b': Key not found diff --git a/testdata/help__del__ok.ct b/testdata/help__del__ok.ct index a87a965..668595f 100644 --- a/testdata/help__del__ok.ct +++ b/testdata/help__del__ok.ct @@ -1,9 +1,9 @@ $ pda help del $ pda del --help -Delete a key. Optionally specify a db. +Delete one or more keys. Optionally specify a db. Usage: - pda del KEY[@DB] [flags] + pda del KEY[@DB] [KEY[@DB] ...] [flags] Aliases: del, delete, rm, remove @@ -11,10 +11,10 @@ Aliases: Flags: -f, --force Force delete without confirmation -h, --help help for del -Delete a key. Optionally specify a db. +Delete one or more keys. Optionally specify a db. Usage: - pda del KEY[@DB] [flags] + pda del KEY[@DB] [KEY[@DB] ...] [flags] Aliases: del, delete, rm, remove diff --git a/testdata/help__ok.ct b/testdata/help__ok.ct index ecaf583..20b0c8c 100644 --- a/testdata/help__ok.ct +++ b/testdata/help__ok.ct @@ -15,7 +15,7 @@ Usage: Available Commands: completion Generate the autocompletion script for the specified shell cp Make a copy of a key. - del Delete a key. Optionally specify a db. + del Delete one or more keys. Optionally specify a db. del-db Delete a database. dump Dump all key/value pairs as NDJSON get Get a value for a key. Optionally specify a db. @@ -46,7 +46,7 @@ Usage: Available Commands: completion Generate the autocompletion script for the specified shell cp Make a copy of a key. - del Delete a key. Optionally specify a db. + del Delete one or more keys. Optionally specify a db. del-db Delete a database. dump Dump all key/value pairs as NDJSON get Get a value for a key. Optionally specify a db. diff --git a/testdata/root__ok.ct b/testdata/root__ok.ct index c0b6c8f..f0d9530 100644 --- a/testdata/root__ok.ct +++ b/testdata/root__ok.ct @@ -14,7 +14,7 @@ Usage: Available Commands: completion Generate the autocompletion script for the specified shell cp Make a copy of a key. - del Delete a key. Optionally specify a db. + del Delete one or more keys. Optionally specify a db. del-db Delete a database. dump Dump all key/value pairs as NDJSON get Get a value for a key. Optionally specify a db.