revert: removes --secrets - to be replaced with encryption

This commit is contained in:
Lewis Wynne 2026-02-10 23:22:06 +00:00
parent 34970ac9d9
commit 4509611185
27 changed files with 132 additions and 269 deletions

View file

@ -40,7 +40,6 @@ type dumpEntry struct {
Key string `json:"key"` Key string `json:"key"`
Value string `json:"value"` Value string `json:"value"`
Encoding string `json:"encoding,omitempty"` Encoding string `json:"encoding,omitempty"`
Secret bool `json:"secret,omitempty"`
ExpiresAt *int64 `json:"expires_at,omitempty"` ExpiresAt *int64 `json:"expires_at,omitempty"`
} }
@ -82,10 +81,6 @@ func dump(cmd *cobra.Command, args []string) error {
return fmt.Errorf("cannot dump '%s': unsupported encoding '%s'", targetDB, mode) return fmt.Errorf("cannot dump '%s': unsupported encoding '%s'", targetDB, mode)
} }
includeSecret, err := cmd.Flags().GetBool("secret")
if err != nil {
return err
}
globPatterns, err := cmd.Flags().GetStringSlice("glob") globPatterns, err := cmd.Flags().GetStringSlice("glob")
if err != nil { if err != nil {
return fmt.Errorf("cannot dump '%s': %v", targetDB, err) return fmt.Errorf("cannot dump '%s': %v", targetDB, err)
@ -100,17 +95,15 @@ func dump(cmd *cobra.Command, args []string) error {
} }
opts := DumpOptions{ opts := DumpOptions{
Encoding: mode, Encoding: mode,
IncludeSecret: includeSecret, Matchers: matchers,
Matchers: matchers, GlobPatterns: globPatterns,
GlobPatterns: globPatterns,
} }
return dumpDatabase(store, strings.TrimPrefix(targetDB, "@"), cmd.OutOrStdout(), opts) return dumpDatabase(store, strings.TrimPrefix(targetDB, "@"), cmd.OutOrStdout(), opts)
} }
func init() { func init() {
dumpCmd.Flags().StringP("encoding", "e", "auto", "value encoding: auto, base64, or text") dumpCmd.Flags().StringP("encoding", "e", "auto", "value encoding: auto, base64, or text")
dumpCmd.Flags().Bool("secret", false, "Include entries marked as secret")
dumpCmd.Flags().StringSliceP("glob", "g", nil, "Filter keys with glob pattern (repeatable)") dumpCmd.Flags().StringSliceP("glob", "g", nil, "Filter keys with glob pattern (repeatable)")
dumpCmd.Flags().String("glob-sep", "", fmt.Sprintf("Characters treated as separators for globbing (default %q)", defaultGlobSeparatorsDisplay())) dumpCmd.Flags().String("glob-sep", "", fmt.Sprintf("Characters treated as separators for globbing (default %q)", defaultGlobSeparatorsDisplay()))
rootCmd.AddCommand(dumpCmd) rootCmd.AddCommand(dumpCmd)
@ -132,10 +125,9 @@ func encodeText(entry *dumpEntry, key []byte, v []byte) error {
// DumpOptions controls how a store is dumped to NDJSON. // DumpOptions controls how a store is dumped to NDJSON.
type DumpOptions struct { type DumpOptions struct {
Encoding string Encoding string
IncludeSecret bool Matchers []glob.Glob
Matchers []glob.Glob GlobPatterns []string
GlobPatterns []string
} }
// dumpDatabase writes entries from dbName to w as NDJSON. // dumpDatabase writes entries from dbName to w as NDJSON.
@ -159,16 +151,10 @@ func dumpDatabase(store *Store, dbName string, w io.Writer, opts DumpOptions) er
if !globMatch(opts.Matchers, string(key)) { if !globMatch(opts.Matchers, string(key)) {
continue continue
} }
meta := item.UserMeta()
isSecret := meta&metaSecret != 0
if isSecret && !opts.IncludeSecret {
continue
}
expiresAt := item.ExpiresAt() expiresAt := item.ExpiresAt()
if err := item.Value(func(v []byte) error { if err := item.Value(func(v []byte) error {
entry := dumpEntry{ entry := dumpEntry{
Key: string(key), Key: string(key),
Secret: isSecret,
} }
if expiresAt > 0 { if expiresAt > 0 {
ts := int64(expiresAt) ts := int64(expiresAt)

View file

@ -74,7 +74,6 @@ func get(cmd *cobra.Command, args []string) error {
store := &Store{} store := &Store{}
var v []byte var v []byte
var meta byte
trans := TransactionArgs{ trans := TransactionArgs{
key: args[0], key: args[0],
readonly: true, readonly: true,
@ -84,7 +83,6 @@ func get(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return err return err
} }
meta = item.UserMeta()
v, err = item.ValueCopy(nil) v, err = item.ValueCopy(nil)
return err return err
}, },
@ -94,14 +92,6 @@ func get(cmd *cobra.Command, args []string) error {
return fmt.Errorf("cannot get '%s': %v", args[0], err) return fmt.Errorf("cannot get '%s': %v", args[0], err)
} }
includeSecret, err := cmd.Flags().GetBool("secret")
if err != nil {
return fmt.Errorf("cannot get '%s': %v", args[0], err)
}
if meta&metaSecret != 0 && !includeSecret {
return fmt.Errorf("cannot get '%s': marked as secret, run with --secret", args[0])
}
binary, err := cmd.Flags().GetBool("include-binary") binary, err := cmd.Flags().GetBool("include-binary")
if err != nil { if err != nil {
return fmt.Errorf("cannot get '%s': %v", args[0], err) return fmt.Errorf("cannot get '%s': %v", args[0], err)
@ -238,13 +228,11 @@ var runFlag bool
func init() { func init() {
getCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output") getCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output")
getCmd.Flags().Bool("secret", false, "display values marked as secret")
getCmd.Flags().BoolVarP(&runFlag, "run", "c", false, "execute the result as a shell command") getCmd.Flags().BoolVarP(&runFlag, "run", "c", false, "execute the result as a shell command")
getCmd.Flags().Bool("no-template", false, "directly output template syntax") getCmd.Flags().Bool("no-template", false, "directly output template syntax")
rootCmd.AddCommand(getCmd) rootCmd.AddCommand(getCmd)
runCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output") runCmd.Flags().BoolP("include-binary", "b", false, "include binary data in text output")
runCmd.Flags().Bool("secret", false, "display values marked as secret")
runCmd.Flags().Bool("no-template", false, "directly output template syntax") runCmd.Flags().Bool("no-template", false, "directly output template syntax")
rootCmd.AddCommand(runCmd) rootCmd.AddCommand(runCmd)
} }

View file

@ -55,7 +55,6 @@ func (e *formatEnum) Type() string { return "format" }
var ( var (
listBinary bool listBinary bool
listSecret bool
listNoKeys bool listNoKeys bool
listNoValues bool listNoValues bool
listTTL bool listTTL bool
@ -142,7 +141,6 @@ func list(cmd *cobra.Command, args []string) error {
tw.AppendHeader(headerRow(columns)) tw.AppendHeader(headerRow(columns))
} }
placeholder := "**********"
var matchedCount int var matchedCount int
trans := TransactionArgs{ trans := TransactionArgs{
key: targetDB, key: targetDB,
@ -162,11 +160,9 @@ func list(cmd *cobra.Command, args []string) error {
continue continue
} }
matchedCount++ matchedCount++
meta := item.UserMeta()
isSecret := meta&metaSecret != 0
var valueStr string var valueStr string
if showValues && (!isSecret || listSecret) { if showValues {
if err := item.Value(func(v []byte) error { if err := item.Value(func(v []byte) error {
valueBuf = append(valueBuf[:0], v...) valueBuf = append(valueBuf[:0], v...)
return nil return nil
@ -182,11 +178,7 @@ func list(cmd *cobra.Command, args []string) error {
case columnKey: case columnKey:
row = append(row, key) row = append(row, key)
case columnValue: case columnValue:
if isSecret && !listSecret { row = append(row, valueStr)
row = append(row, placeholder)
} else {
row = append(row, valueStr)
}
case columnTTL: case columnTTL:
row = append(row, formatExpiry(item.ExpiresAt())) row = append(row, formatExpiry(item.ExpiresAt()))
} }
@ -310,7 +302,6 @@ func renderTable(tw table.Writer) {
func init() { func init() {
listCmd.Flags().BoolVarP(&listBinary, "binary", "b", false, "include binary data in text output") listCmd.Flags().BoolVarP(&listBinary, "binary", "b", false, "include binary data in text output")
listCmd.Flags().BoolVarP(&listSecret, "secret", "S", false, "display values marked as secret")
listCmd.Flags().BoolVar(&listNoKeys, "no-keys", false, "suppress the key column") listCmd.Flags().BoolVar(&listNoKeys, "no-keys", false, "suppress the key column")
listCmd.Flags().BoolVar(&listNoValues, "no-values", false, "suppress the value column") listCmd.Flags().BoolVar(&listNoValues, "no-values", false, "suppress the value column")
listCmd.Flags().BoolVarP(&listTTL, "ttl", "t", false, "append a TTL column when entries expire") listCmd.Flags().BoolVarP(&listTTL, "ttl", "t", false, "append a TTL column when entries expire")

View file

@ -32,6 +32,7 @@ import (
"strings" "strings"
"github.com/dgraph-io/badger/v4" "github.com/dgraph-io/badger/v4"
"github.com/gobwas/glob"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -85,82 +86,21 @@ func restore(cmd *cobra.Command, args []string) error {
decoder := json.NewDecoder(bufio.NewReaderSize(reader, 8*1024*1024)) decoder := json.NewDecoder(bufio.NewReaderSize(reader, 8*1024*1024))
wb := db.NewWriteBatch()
defer wb.Cancel()
interactive, err := cmd.Flags().GetBool("interactive") interactive, err := cmd.Flags().GetBool("interactive")
if err != nil { if err != nil {
return fmt.Errorf("cannot restore '%s': %v", displayTarget, err) return fmt.Errorf("cannot restore '%s': %v", displayTarget, err)
} }
promptOverwrite := interactive || config.Key.AlwaysPromptOverwrite promptOverwrite := interactive || config.Key.AlwaysPromptOverwrite
entryNo := 0 restored, err := restoreEntries(decoder, db, restoreOpts{
var restored int matchers: matchers,
var matched bool promptOverwrite: promptOverwrite,
})
for { if err != nil {
var entry dumpEntry
if err := decoder.Decode(&entry); err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("cannot restore '%s': entry %d: %w", displayTarget, entryNo+1, err)
}
entryNo++
if entry.Key == "" {
return fmt.Errorf("cannot restore '%s': entry %d: missing key", displayTarget, entryNo)
}
if !globMatch(matchers, entry.Key) {
continue
}
if promptOverwrite {
exists, err := keyExistsInDB(db, entry.Key)
if err != nil {
return fmt.Errorf("cannot restore '%s': entry %d: %v", displayTarget, entryNo, err)
}
if exists {
fmt.Printf("overwrite '%s'? (y/n)\n", entry.Key)
var confirm string
if _, err := fmt.Scanln(&confirm); err != nil {
return fmt.Errorf("cannot restore '%s': entry %d: %v", displayTarget, entryNo, err)
}
if strings.ToLower(confirm) != "y" {
continue
}
}
}
value, err := decodeEntryValue(entry)
if err != nil {
return fmt.Errorf("cannot restore '%s': entry %d: %w", displayTarget, entryNo, err)
}
entryMeta := byte(0x0)
if entry.Secret {
entryMeta = metaSecret
}
writeEntry := badger.NewEntry([]byte(entry.Key), value).WithMeta(entryMeta)
if entry.ExpiresAt != nil {
if *entry.ExpiresAt < 0 {
return fmt.Errorf("cannot restore '%s': entry %d: expires_at must be >= 0", displayTarget, entryNo)
}
writeEntry.ExpiresAt = uint64(*entry.ExpiresAt)
}
if err := wb.SetEntry(writeEntry); err != nil {
return fmt.Errorf("cannot restore '%s': entry %d: %w", displayTarget, entryNo, err)
}
restored++
matched = true
}
if err := wb.Flush(); err != nil {
return fmt.Errorf("cannot restore '%s': %v", displayTarget, err) return fmt.Errorf("cannot restore '%s': %v", displayTarget, err)
} }
if len(matchers) > 0 && !matched { if len(matchers) > 0 && restored == 0 {
return fmt.Errorf("cannot restore '%s': No matches for pattern %s", displayTarget, formatGlobPatterns(globPatterns)) return fmt.Errorf("cannot restore '%s': No matches for pattern %s", displayTarget, formatGlobPatterns(globPatterns))
} }
@ -198,6 +138,76 @@ func decodeEntryValue(entry dumpEntry) ([]byte, error) {
} }
} }
type restoreOpts struct {
matchers []glob.Glob
promptOverwrite bool
}
func restoreEntries(decoder *json.Decoder, db *badger.DB, opts restoreOpts) (int, error) {
wb := db.NewWriteBatch()
defer wb.Cancel()
entryNo := 0
restored := 0
for {
var entry dumpEntry
if err := decoder.Decode(&entry); err != nil {
if err == io.EOF {
break
}
return 0, fmt.Errorf("entry %d: %w", entryNo+1, err)
}
entryNo++
if entry.Key == "" {
return 0, fmt.Errorf("entry %d: missing key", entryNo)
}
if !globMatch(opts.matchers, entry.Key) {
continue
}
if opts.promptOverwrite {
exists, err := keyExistsInDB(db, entry.Key)
if err != nil {
return 0, fmt.Errorf("entry %d: %v", entryNo, err)
}
if exists {
fmt.Printf("overwrite '%s'? (y/n)\n", entry.Key)
var confirm string
if _, err := fmt.Scanln(&confirm); err != nil {
return 0, fmt.Errorf("entry %d: %v", entryNo, err)
}
if strings.ToLower(confirm) != "y" {
continue
}
}
}
value, err := decodeEntryValue(entry)
if err != nil {
return 0, fmt.Errorf("entry %d: %w", entryNo, err)
}
writeEntry := badger.NewEntry([]byte(entry.Key), value)
if entry.ExpiresAt != nil {
if *entry.ExpiresAt < 0 {
return 0, fmt.Errorf("entry %d: expires_at must be >= 0", entryNo)
}
writeEntry.ExpiresAt = uint64(*entry.ExpiresAt)
}
if err := wb.SetEntry(writeEntry); err != nil {
return 0, fmt.Errorf("entry %d: %w", entryNo, err)
}
restored++
}
if err := wb.Flush(); err != nil {
return 0, err
}
return restored, nil
}
func init() { func init() {
restoreCmd.Flags().StringP("file", "f", "", "Path to an NDJSON dump (defaults to stdin)") restoreCmd.Flags().StringP("file", "f", "", "Path to an NDJSON dump (defaults to stdin)")
restoreCmd.Flags().StringSliceP("glob", "g", nil, "Restore keys matching glob pattern (repeatable)") restoreCmd.Flags().StringSliceP("glob", "g", nil, "Restore keys matching glob pattern (repeatable)")

View file

@ -76,10 +76,6 @@ func set(cmd *cobra.Command, args []string) error {
value = bytes value = bytes
} }
secret, err := cmd.Flags().GetBool("secret")
if err != nil {
return fmt.Errorf("cannot set '%s': %v", args[0], err)
}
ttl, err := cmd.Flags().GetDuration("ttl") ttl, err := cmd.Flags().GetDuration("ttl")
if err != nil { if err != nil {
return fmt.Errorf("cannot set '%s': %v", args[0], err) return fmt.Errorf("cannot set '%s': %v", args[0], err)
@ -108,9 +104,6 @@ func set(cmd *cobra.Command, args []string) error {
sync: false, sync: false,
transact: func(tx *badger.Txn, k []byte) error { transact: func(tx *badger.Txn, k []byte) error {
entry := badger.NewEntry(k, value) entry := badger.NewEntry(k, value)
if secret {
entry = entry.WithMeta(metaSecret)
}
if ttl != 0 { if ttl != 0 {
entry = entry.WithTTL(ttl) entry = entry.WithTTL(ttl)
} }
@ -127,7 +120,6 @@ func set(cmd *cobra.Command, args []string) error {
func init() { func init() {
rootCmd.AddCommand(setCmd) rootCmd.AddCommand(setCmd)
setCmd.Flags().Bool("secret", false, "Mark the stored value as a secret")
setCmd.Flags().DurationP("ttl", "t", 0, "Expire the key after the provided duration (e.g. 24h, 30m)") setCmd.Flags().DurationP("ttl", "t", 0, "Expire the key after the provided duration (e.g. 24h, 30m)")
setCmd.Flags().BoolP("interactive", "i", false, "Prompt before overwriting an existing key") setCmd.Flags().BoolP("interactive", "i", false, "Prompt before overwriting an existing key")
} }

View file

@ -41,10 +41,6 @@ type errNotFound struct {
suggestions []string suggestions []string
} }
const (
metaSecret byte = 0x1
)
func (err errNotFound) Error() string { func (err errNotFound) Error() string {
if len(err.suggestions) == 0 { if len(err.suggestions) == 0 {
return "No such key" return "No such key"

View file

@ -64,35 +64,36 @@ func sync(manual bool) error {
} }
remoteAhead, behind, err := repoAheadBehind(repoDir, remoteInfo.Ref) remoteAhead, behind, err := repoAheadBehind(repoDir, remoteInfo.Ref)
if err != nil { if err != nil {
return err ahead = 1 // ref doesn't exist yet; just push
} } else {
ahead = remoteAhead ahead = remoteAhead
if behind > 0 { if behind > 0 {
if ahead > 0 { if ahead > 0 {
return fmt.Errorf("repo diverged from remote (ahead %d, behind %d); resolve manually", ahead, behind) return fmt.Errorf("repo diverged from remote (ahead %d, behind %d); resolve manually", ahead, behind)
} }
fmt.Printf("remote has %d commit(s) not present locally; discard local changes and pull? (y/n)\n", behind) fmt.Printf("remote has %d commit(s) not present locally; discard local changes and pull? (y/n)\n", behind)
var confirm string var confirm string
if _, err := fmt.Scanln(&confirm); err != nil { if _, err := fmt.Scanln(&confirm); err != nil {
return fmt.Errorf("cannot continue sync: %w", err) return fmt.Errorf("cannot continue sync: %w", err)
} }
if strings.ToLower(confirm) != "y" { if strings.ToLower(confirm) != "y" {
return fmt.Errorf("aborted sync") return fmt.Errorf("aborted sync")
} }
dirty, err := repoHasChanges(repoDir) dirty, err := repoHasChanges(repoDir)
if err != nil { if err != nil {
return err
}
if dirty {
stashMsg := fmt.Sprintf("pda sync: %s", time.Now().UTC().Format(time.RFC3339))
if err := runGit(repoDir, "stash", "push", "-u", "-m", stashMsg); err != nil {
return err return err
} }
if dirty {
stashMsg := fmt.Sprintf("pda sync: %s", time.Now().UTC().Format(time.RFC3339))
if err := runGit(repoDir, "stash", "push", "-u", "-m", stashMsg); err != nil {
return err
}
}
if err := pullRemote(repoDir, remoteInfo); err != nil {
return err
}
return restoreAllSnapshots(store, repoDir)
} }
if err := pullRemote(repoDir, remoteInfo); err != nil {
return err
}
return restoreAllSnapshots(store, repoDir)
} }
} }
@ -108,7 +109,9 @@ func sync(manual bool) error {
} }
madeCommit := false madeCommit := false
if !changed { if !changed {
fmt.Println("no changes to commit") if manual {
fmt.Println("no changes to commit")
}
} else { } else {
msg := fmt.Sprintf("sync: %s", time.Now().UTC().Format(time.RFC3339)) msg := fmt.Sprintf("sync: %s", time.Now().UTC().Format(time.RFC3339))
if err := runGit(repoDir, "commit", "-m", msg); err != nil { if err := runGit(repoDir, "commit", "-m", msg); err != nil {
@ -117,10 +120,15 @@ func sync(manual bool) error {
madeCommit = true madeCommit = true
} }
if manual || config.Git.AutoPush { if manual || config.Git.AutoPush {
if remoteInfo.Ref != "" && (madeCommit || ahead > 0) { if remoteInfo.Ref == "" {
if manual {
fmt.Println("no remote configured; skipping push")
}
} else if madeCommit || ahead > 0 {
return pushRemote(repoDir, remoteInfo) return pushRemote(repoDir, remoteInfo)
} else if manual {
fmt.Println("nothing to push")
} }
fmt.Println("no remote configured; skipping push")
} }
return nil return nil
} }

View file

@ -12,7 +12,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/dgraph-io/badger/v4"
gap "github.com/muesli/go-app-paths" gap "github.com/muesli/go-app-paths"
) )
@ -63,7 +62,7 @@ func writeGitignore(repoDir string) error {
if err := runGit(repoDir, "add", ".gitignore"); err != nil { if err := runGit(repoDir, "add", ".gitignore"); err != nil {
return err return err
} }
return runGit(repoDir, "commit", "--allow-empty", "-m", "generated gitignore") return runGit(repoDir, "commit", "-m", "generated gitignore")
} }
fmt.Println("Existing .gitignore found.") fmt.Println("Existing .gitignore found.")
return nil return nil
@ -82,8 +81,7 @@ func snapshotDB(store *Store, repoDir, db string) error {
defer f.Close() defer f.Close()
opts := DumpOptions{ opts := DumpOptions{
Encoding: "auto", Encoding: "auto",
IncludeSecret: false,
} }
if err := dumpDatabase(store, db, f, opts); err != nil { if err := dumpDatabase(store, db, f, opts); err != nil {
return err return err
@ -373,60 +371,7 @@ func restoreSnapshot(store *Store, path string, dbName string) error {
defer db.Close() defer db.Close()
decoder := json.NewDecoder(bufio.NewReader(f)) decoder := json.NewDecoder(bufio.NewReader(f))
wb := db.NewWriteBatch() _, err = restoreEntries(decoder, db, restoreOpts{})
defer wb.Cancel() return err
entryNo := 0
for {
var entry dumpEntry
if err := decoder.Decode(&entry); err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("entry %d: %w", entryNo+1, err)
}
entryNo++
if entry.Key == "" {
return fmt.Errorf("entry %d: missing key", entryNo)
}
value, err := decodeEntryValue(entry)
if err != nil {
return fmt.Errorf("entry %d: %w", entryNo, err)
}
entryMeta := byte(0x0)
if entry.Secret {
entryMeta = metaSecret
}
writeEntry := badger.NewEntry([]byte(entry.Key), value).WithMeta(entryMeta)
if entry.ExpiresAt != nil {
if *entry.ExpiresAt < 0 {
return fmt.Errorf("entry %d: expires_at must be >= 0", entryNo)
}
writeEntry.ExpiresAt = uint64(*entry.ExpiresAt)
}
if err := wb.SetEntry(writeEntry); err != nil {
return fmt.Errorf("entry %d: %w", entryNo, err)
}
}
if err := wb.Flush(); err != nil {
return err
}
return nil
} }
// hasMergeConflicts returns true if there are files with unresolved merge
// conflicts in the working tree.
func hasMergeConflicts(dir string) (bool, error) {
cmd := exec.Command("git", "diff", "--name-only", "--diff-filter=U")
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
return false, err
}
return len(bytes.TrimSpace(out)) > 0, nil
}

View file

@ -8,7 +8,7 @@ $ pda get foobar --secret --> FAIL
Error: cannot get 'foobar': Key not found Error: cannot get 'foobar': Key not found
Error: cannot get 'foobar': Key not found Error: cannot get 'foobar': Key not found
Error: cannot get 'foobar': Key not found Error: cannot get 'foobar': Key not found
Error: unknown flag: --secret
Error: cannot get 'foobar': Key not found Error: cannot get 'foobar': Key not found
Error: cannot get 'foobar': Key not found Error: unknown flag: --secret
Error: cannot get 'foobar': Key not found Error: unknown flag: --secret
Error: cannot get 'foobar': Key not found

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello
$ pda set foo < cmd
$ pda get foo --include-binary --run --secret
hello

View file

@ -1,6 +0,0 @@
$ fecho cmd echo hello
$ pda set a < cmd
$ pda get a
echo hello
$ pda get a --run --secret
hello

View file

@ -1,3 +0,0 @@
$ pda set foo bar
$ pda get foo --secret
bar

View file

@ -1,3 +0,0 @@
$ pda set a b --secret
$ pda get a --> FAIL
Error: cannot get 'a': marked as secret, run with --secret

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --include-binary --> FAIL
Error: cannot get 'a': marked as secret, run with --secret

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --include-binary --run --> FAIL
Error: cannot get 'a': marked as secret, run with --secret

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --run --> FAIL
Error: cannot get 'a': marked as secret, run with --secret

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --secret --run --include-binary
hello world

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --include-binary --secret
echo hello world

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --run --secret
hello world

View file

@ -1,4 +0,0 @@
$ fecho cmd echo hello world
$ pda set a --secret < cmd
$ pda get a --secret
echo hello world

View file

@ -13,7 +13,6 @@ Flags:
-g, --glob strings Filter keys with glob pattern (repeatable) -g, --glob strings Filter keys with glob pattern (repeatable)
--glob-sep string Characters treated as separators for globbing (default "/-_.@: ") --glob-sep string Characters treated as separators for globbing (default "/-_.@: ")
-h, --help help for export -h, --help help for export
--secret Include entries marked as secret
Dump all key/value pairs as NDJSON Dump all key/value pairs as NDJSON
Usage: Usage:
@ -27,4 +26,3 @@ Flags:
-g, --glob strings Filter keys with glob pattern (repeatable) -g, --glob strings Filter keys with glob pattern (repeatable)
--glob-sep string Characters treated as separators for globbing (default "/-_.@: ") --glob-sep string Characters treated as separators for globbing (default "/-_.@: ")
-h, --help help for export -h, --help help for export
--secret Include entries marked as secret

View file

@ -20,7 +20,6 @@ Flags:
-b, --include-binary include binary data in text output -b, --include-binary include binary data in text output
--no-template directly output template syntax --no-template directly output template syntax
-c, --run execute the result as a shell command -c, --run execute the result as a shell command
--secret display values marked as secret
Get the value of a key. Optionally specify a store. Get the value of a key. Optionally specify a store.
{{ .TEMPLATES }} can be filled by passing TEMPLATE=VALUE as an {{ .TEMPLATES }} can be filled by passing TEMPLATE=VALUE as an
@ -41,4 +40,3 @@ Flags:
-b, --include-binary include binary data in text output -b, --include-binary include binary data in text output
--no-template directly output template syntax --no-template directly output template syntax
-c, --run execute the result as a shell command -c, --run execute the result as a shell command
--secret display values marked as secret

View file

@ -17,7 +17,6 @@ Flags:
-h, --help help for list -h, --help help for list
--no-keys suppress the key column --no-keys suppress the key column
--no-values suppress the value column --no-values suppress the value column
-S, --secret display values marked as secret
-t, --ttl append a TTL column when entries expire -t, --ttl append a TTL column when entries expire
List the contents of a store List the contents of a store
@ -36,5 +35,4 @@ Flags:
-h, --help help for list -h, --help help for list
--no-keys suppress the key column --no-keys suppress the key column
--no-values suppress the value column --no-values suppress the value column
-S, --secret display values marked as secret
-t, --ttl append a TTL column when entries expire -t, --ttl append a TTL column when entries expire

View file

@ -20,7 +20,6 @@ Aliases:
Flags: Flags:
-h, --help help for set -h, --help help for set
-i, --interactive Prompt before overwriting an existing key -i, --interactive Prompt before overwriting an existing key
--secret Mark the stored value as a secret
-t, --ttl duration Expire the key after the provided duration (e.g. 24h, 30m) -t, --ttl duration Expire the key after the provided duration (e.g. 24h, 30m)
Set a key to a given value or stdin. Optionally specify a store. Set a key to a given value or stdin. Optionally specify a store.
@ -42,5 +41,4 @@ Aliases:
Flags: Flags:
-h, --help help for set -h, --help help for set
-i, --interactive Prompt before overwriting an existing key -i, --interactive Prompt before overwriting an existing key
--secret Mark the stored value as a secret
-t, --ttl duration Expire the key after the provided duration (e.g. 24h, 30m) -t, --ttl duration Expire the key after the provided duration (e.g. 24h, 30m)

View file

@ -1,7 +1,8 @@
$ pda set foo 1 $ pda set foo 1
$ pda set bar 2 $ pda set bar 2
$ pda ls $ pda ls
a ********** a echo hello
a1 1 a1 1
a2 2 a2 2
b1 3 b1 3

View file

@ -1 +0,0 @@
$ pda set foo foobar --secret

View file

@ -1 +0,0 @@
$ pda set a b --secret --ttl 10m