commit 2c1b44750cec31c186e830c037b308d009c2fb9b
parent 15f8a410c7d3847051f827e286f72d757f40292b
Author: Sean Enck <sean@ttypty.com>
Date: Thu, 30 Mar 2023 20:11:24 -0400
stats has been replaced by json
Diffstat:
15 files changed, 201 insertions(+), 206 deletions(-)
diff --git a/cmd/main.go b/cmd/main.go
@@ -84,8 +84,8 @@ func run() error {
return app.Insert(p, mode)
case cli.RemoveCommand:
return app.Remove(p)
- case cli.StatsCommand:
- return app.Stats(p)
+ case cli.JSONCommand:
+ return app.JSON(p)
case cli.ShowCommand, cli.ClipCommand:
return app.ShowClip(p, command == cli.ShowCommand)
case cli.ConvCommand:
diff --git a/internal/app/conv.go b/internal/app/conv.go
@@ -3,7 +3,7 @@ package app
import (
"errors"
"fmt"
- "strings"
+ "io"
"github.com/enckse/lockbox/internal/backend"
)
@@ -20,13 +20,25 @@ func Conv(cmd CommandOptions) error {
if err != nil {
return err
}
- e, err := t.QueryCallback(backend.QueryOptions{Mode: backend.ListMode, Values: backend.HashedValue})
- if err != nil {
+ if err := serialize(w, t); err != nil {
return err
}
- for _, item := range e {
- fmt.Fprintf(w, "%s:\n %s\n\n", item.Path, strings.ReplaceAll(item.Value, "\n", "\n "))
+ }
+ return nil
+}
+
+func serialize(w io.Writer, tx *backend.Transaction) error {
+ e, err := tx.QueryCallback(backend.QueryOptions{Mode: backend.ListMode, Values: backend.JSONValue})
+ if err != nil {
+ return err
+ }
+ fmt.Fprintf(w, "[")
+ for idx, item := range e {
+ if idx > 0 {
+ fmt.Fprint(w, ",")
}
+ fmt.Fprintf(w, "\n%s\n", item.Value)
}
+ fmt.Fprintf(w, "]")
return nil
}
diff --git a/internal/app/json.go b/internal/app/json.go
@@ -0,0 +1,29 @@
+// Package app can get stats
+package app
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/enckse/lockbox/internal/backend"
+)
+
+// JSON will get entries (1 or ALL) in JSON format
+func JSON(cmd CommandOptions) error {
+ args := cmd.Args()
+ if len(args) > 1 {
+ return errors.New("invalid arguments")
+ }
+ if len(args) == 0 {
+ return serialize(cmd.Writer(), cmd.Transaction())
+ }
+ entry := args[0]
+ v, err := cmd.Transaction().Get(entry, backend.JSONValue)
+ if err != nil {
+ return fmt.Errorf("unable to get stats: %w", err)
+ }
+ if v != nil {
+ fmt.Fprintln(cmd.Writer(), v.Value)
+ }
+ return nil
+}
diff --git a/internal/app/json_test.go b/internal/app/json_test.go
@@ -0,0 +1,34 @@
+package app_test
+
+import (
+ "bytes"
+ "testing"
+
+ "github.com/enckse/lockbox/internal/app"
+)
+
+func TestJSON(t *testing.T) {
+ m := newMockCommand(t)
+ if err := app.JSON(m); err != nil {
+ t.Errorf("invalid error: %v", err)
+ }
+ m.args = []string{"test", "test2"}
+ if err := app.JSON(m); err.Error() != "invalid arguments" {
+ t.Errorf("invalid error: %v", err)
+ }
+ m.args = []string{"test/test2/test1"}
+ if err := app.JSON(m); err != nil {
+ t.Errorf("invalid error: %v", err)
+ }
+ if m.buf.String() == "" {
+ t.Error("no stats")
+ }
+ m.buf = bytes.Buffer{}
+ m.args = []string{"tsest/test2/test1"}
+ if err := app.JSON(m); err != nil {
+ t.Errorf("invalid error: %v", err)
+ }
+ if m.buf.String() != "" {
+ t.Error("no stats")
+ }
+}
diff --git a/internal/app/rekey.go b/internal/app/rekey.go
@@ -1,6 +1,7 @@
package app
import (
+ "encoding/json"
"errors"
"fmt"
"io"
@@ -16,8 +17,7 @@ import (
type (
// Keyer defines how rekeying happens
Keyer interface {
- List() ([]string, error)
- Stats(string) ([]string, error)
+ JSON() ([]backend.JSON, error)
Show(string) ([]byte, error)
Insert(ReKeyEntry) error
}
@@ -42,27 +42,22 @@ func NewDefaultKeyer() (DefaultKeyer, error) {
return DefaultKeyer{exe: exe}, nil
}
-// List will get the list of keys in the store
-func (r DefaultKeyer) List() ([]string, error) {
- return r.getCommandLines(cli.ListCommand)
-}
-
-// Stats will get stats for an entry
-func (r DefaultKeyer) Stats(entry string) ([]string, error) {
- return r.getCommandLines(cli.StatsCommand, entry)
+// Show will get entry payload
+func (r DefaultKeyer) Show(entry string) ([]byte, error) {
+ return exec.Command(r.exe, cli.ShowCommand, entry).Output()
}
-func (r DefaultKeyer) getCommandLines(args ...string) ([]string, error) {
- out, err := exec.Command(r.exe, args...).Output()
+// JSON will get the JSON backing entries
+func (r DefaultKeyer) JSON() ([]backend.JSON, error) {
+ out, err := exec.Command(r.exe, cli.JSONCommand).Output()
if err != nil {
return nil, err
}
- return strings.Split(strings.TrimSpace(string(out)), "\n"), nil
-}
-
-// Show will get entry payload
-func (r DefaultKeyer) Show(entry string) ([]byte, error) {
- return exec.Command(r.exe, cli.ShowCommand, entry).Output()
+ var j []backend.JSON
+ if err := json.Unmarshal(out, &j); err != nil {
+ return nil, err
+ }
+ return j, nil
}
// Insert will insert the rekeying entry
@@ -88,39 +83,26 @@ func ReKey(writer io.Writer, r Keyer) error {
if err != nil {
return err
}
- entries, err := r.List()
+ entries, err := r.JSON()
if err != nil {
return err
}
for _, entry := range entries {
- if _, err := fmt.Fprintf(writer, "rekeying: %s\n", entry); err != nil {
+ if _, err := fmt.Fprintf(writer, "rekeying: %s\n", entry.Path); err != nil {
return err
}
- stats, err := r.Stats(entry)
- if err != nil {
- return fmt.Errorf("failed to get modtime, command failed: %w", err)
- }
- modTime := ""
- for _, stat := range stats {
- if strings.HasPrefix(stat, backend.ModTimeField) {
- if modTime != "" {
- return errors.New("unable to read modtime, too many values")
- }
- modTime = strings.TrimPrefix(stat, backend.ModTimeField)
- }
- }
- modTime = strings.TrimSpace(modTime)
+ modTime := strings.TrimSpace(entry.ModTime)
if modTime == "" {
return errors.New("did not read modtime")
}
- data, err := r.Show(entry)
+ data, err := r.Show(entry.Path)
if err != nil {
return err
}
var insertEnv []string
insertEnv = append(insertEnv, env...)
insertEnv = append(insertEnv, fmt.Sprintf("%s=%s", inputs.ModTimeEnv, modTime))
- if err := r.Insert(ReKeyEntry{Path: entry, Env: insertEnv, Data: data}); err != nil {
+ if err := r.Insert(ReKeyEntry{Path: entry.Path, Env: insertEnv, Data: data}); err != nil {
return err
}
}
diff --git a/internal/app/rekey_test.go b/internal/app/rekey_test.go
@@ -8,23 +8,23 @@ import (
"testing"
"github.com/enckse/lockbox/internal/app"
+ "github.com/enckse/lockbox/internal/backend"
)
type (
mockKeyer struct {
- entries []string
- data map[string][]byte
- stats map[string][]string
- err error
- rekeys []app.ReKeyEntry
+ data map[string][]byte
+ err error
+ rekeys []app.ReKeyEntry
+ items []backend.JSON
}
)
-func (m *mockKeyer) List() ([]string, error) {
+func (m *mockKeyer) JSON() ([]backend.JSON, error) {
if m.err != nil {
return nil, m.err
}
- return m.entries, nil
+ return m.items, nil
}
func (m *mockKeyer) Show(entry string) ([]byte, error) {
@@ -35,14 +35,6 @@ func (m *mockKeyer) Show(entry string) ([]byte, error) {
return val, nil
}
-func (m *mockKeyer) Stats(entry string) ([]string, error) {
- val, ok := m.stats[entry]
- if !ok {
- return nil, errors.New("no stats")
- }
- return val, nil
-}
-
func (m *mockKeyer) Insert(entry app.ReKeyEntry) error {
m.rekeys = append(m.rekeys, entry)
if entry.Path == "error" {
@@ -60,32 +52,23 @@ func TestErrors(t *testing.T) {
setupReKey()
var buf bytes.Buffer
m := &mockKeyer{}
- m.err = errors.New("invalid ls")
- if err := app.ReKey(&buf, m); err == nil || err.Error() != "invalid ls" {
+ m.err = errors.New("invalid call")
+ if err := app.ReKey(&buf, m); err == nil || err.Error() != "invalid call" {
t.Errorf("invalid error: %v", err)
}
m.err = nil
- m.entries = []string{"test1", "error"}
- if err := app.ReKey(&buf, m); err == nil || err.Error() != "failed to get modtime, command failed: no stats" {
- t.Errorf("invalid error: %v", err)
- }
- m.stats = make(map[string][]string)
- m.stats["test1"] = []string{"modtime"}
- m.stats["error"] = []string{"modtime: 3"}
+ m.items = []backend.JSON{{Path: "test1", ModTime: ""}}
if err := app.ReKey(&buf, m); err == nil || err.Error() != "did not read modtime" {
t.Errorf("invalid error: %v", err)
}
- m.stats["test1"] = []string{"modtime: 1", "modtime: 2"}
- if err := app.ReKey(&buf, m); err == nil || err.Error() != "unable to read modtime, too many values" {
- t.Errorf("invalid error: %v", err)
- }
- m.stats["test1"] = []string{"modtime: 1"}
+ m.items = []backend.JSON{{Path: "test1", ModTime: "2"}}
if err := app.ReKey(&buf, m); err == nil || err.Error() != "no data" {
t.Errorf("invalid error: %v", err)
}
m.data = make(map[string][]byte)
m.data["test1"] = []byte{1}
m.data["error"] = []byte{2}
+ m.items = []backend.JSON{{Path: "error", ModTime: "2"}}
if err := app.ReKey(&buf, m); err == nil || err.Error() != "bad insert" {
t.Errorf("invalid error: %v", err)
}
@@ -101,13 +84,10 @@ func TestReKey(t *testing.T) {
t.Error("no data")
}
m := &mockKeyer{}
- m.entries = []string{"test1", "test2"}
+ m.items = []backend.JSON{{Path: "test1", ModTime: "2"}, {Path: "test1", ModTime: "2"}}
m.data = make(map[string][]byte)
m.data["test1"] = []byte{1}
m.data["test2"] = []byte{2}
- m.stats = make(map[string][]string)
- m.stats["test1"] = []string{"modtime: 1", "modtime2"}
- m.stats["test2"] = []string{"moime: 1", "modtime: 2"}
if err := app.ReKey(&buf, m); err != nil {
t.Errorf("invalid error: %v", err)
}
@@ -117,7 +97,7 @@ func TestReKey(t *testing.T) {
if len(m.rekeys) != 2 {
t.Error("invalid rekeys")
}
- if fmt.Sprintf("%v", m.rekeys) != `[{test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=1] [1]} {test2 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [2]}]` {
+ if fmt.Sprintf("%v", m.rekeys) != `[{test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [1]} {test1 [LOCKBOX_KEYMODE= LOCKBOX_KEY=abc LOCKBOX_KEYFILE= LOCKBOX_STORE=store LOCKBOX_SET_MODTIME=2] [1]}]` {
t.Errorf("invalid results: %v", m.rekeys)
}
}
diff --git a/internal/app/stats.go b/internal/app/stats.go
@@ -1,26 +0,0 @@
-// Package app can get stats
-package app
-
-import (
- "errors"
- "fmt"
-
- "github.com/enckse/lockbox/internal/backend"
-)
-
-// Stats will retrieve entry stats
-func Stats(cmd CommandOptions) error {
- args := cmd.Args()
- if len(args) != 1 {
- return errors.New("entry required")
- }
- entry := args[0]
- v, err := cmd.Transaction().Get(entry, backend.StatsValue)
- if err != nil {
- return fmt.Errorf("unable to get stats: %w", err)
- }
- if v != nil {
- fmt.Fprintln(cmd.Writer(), v.Value)
- }
- return nil
-}
diff --git a/internal/app/stats_test.go b/internal/app/stats_test.go
@@ -1,30 +0,0 @@
-package app_test
-
-import (
- "bytes"
- "testing"
-
- "github.com/enckse/lockbox/internal/app"
-)
-
-func TestStats(t *testing.T) {
- m := newMockCommand(t)
- if err := app.Stats(m); err.Error() != "entry required" {
- t.Errorf("invalid error: %v", err)
- }
- m.args = []string{"test/test2/test1"}
- if err := app.Stats(m); err != nil {
- t.Errorf("invalid error: %v", err)
- }
- if m.buf.String() == "" {
- t.Error("no stats")
- }
- m.buf = bytes.Buffer{}
- m.args = []string{"tsest/test2/test1"}
- if err := app.Stats(m); err != nil {
- t.Errorf("invalid error: %v", err)
- }
- if m.buf.String() != "" {
- t.Error("no stats")
- }
-}
diff --git a/internal/backend/query.go b/internal/backend/query.go
@@ -132,7 +132,7 @@ func (t *Transaction) QueryCallback(args QueryOptions) ([]QueryEntity, error) {
switch args.Values {
case JSONValue:
t := getValue(e.backing, modTimeKey)
- s := JSON{Path: k, ModTime: t}
+ s := JSON{Path: k, ModTime: t, Hash: fmt.Sprintf("%x", sha512.Sum512([]byte(val)))}
m, err := json.MarshalIndent(s, "", " ")
if err != nil {
return nil, err
@@ -140,13 +140,6 @@ func (t *Transaction) QueryCallback(args QueryOptions) ([]QueryEntity, error) {
entity.Value = string(m)
case SecretValue:
entity.Value = val
- case HashedValue, StatsValue:
- t := getValue(e.backing, modTimeKey)
- res := fmt.Sprintf("%s %s", ModTimeField, t)
- if args.Values == HashedValue {
- res = fmt.Sprintf("%s\nhash: %x", res, sha512.Sum512([]byte(val)))
- }
- entity.Value = res
}
}
results = append(results, entity)
diff --git a/internal/backend/query_test.go b/internal/backend/query_test.go
@@ -2,7 +2,6 @@ package backend_test
import (
"encoding/json"
- "fmt"
"os"
"strings"
"testing"
@@ -83,21 +82,19 @@ func TestValueModes(t *testing.T) {
if q.Value != "" {
t.Errorf("invalid result value: %s", q.Value)
}
- q, err = fullSetup(t, true).Get("test/test/abc", backend.HashedValue)
+ q, err = fullSetup(t, true).Get("test/test/abc", backend.JSONValue)
if err != nil {
t.Errorf("no error: %v", err)
}
- hash := strings.TrimSpace(q.Value)
- parts := strings.Split(hash, "\n")
- if len(parts) != 2 {
- t.Errorf("invalid hash output: %v", parts)
+ m := backend.JSON{}
+ if err := json.Unmarshal([]byte(q.Value), &m); err != nil {
+ t.Errorf("no error: %v", err)
}
- if parts[1] != "hash: 44276ba24db13df5568aa6db81e0190ab9d35d2168dce43dca61e628f5c666b1d8b091f1dda59c2359c86e7d393d59723a421d58496d279031e7f858c11d893e" {
+ if m.Hash != "44276ba24db13df5568aa6db81e0190ab9d35d2168dce43dca61e628f5c666b1d8b091f1dda59c2359c86e7d393d59723a421d58496d279031e7f858c11d893e" {
t.Errorf("invalid result value: %s", q.Value)
}
- dt := parts[0]
- if !strings.HasPrefix(dt, "modtime: ") || len(dt) <= 20 {
- t.Errorf("invalid date/time: %s", dt)
+ if len(m.ModTime) < 20 {
+ t.Errorf("invalid date/time")
}
q, err = fullSetup(t, true).Get("test/test/ab11c", backend.SecretValue)
if err != nil {
@@ -106,19 +103,15 @@ func TestValueModes(t *testing.T) {
if q.Value != "tdest\ntest" {
t.Errorf("invalid result value: %s", q.Value)
}
- q, err = fullSetup(t, true).Get("test/test/abc", backend.StatsValue)
- if err != nil || !strings.HasPrefix(q.Value, "modtime: ") || len(strings.Split(q.Value, "\n")) != 1 {
- t.Errorf("invalid stats: %s", q.Value)
- }
q, err = fullSetup(t, true).Get("test/test/abc", backend.JSONValue)
if err != nil {
t.Errorf("no error: %v", err)
}
- m := backend.JSON{}
+ m = backend.JSON{}
if err := json.Unmarshal([]byte(q.Value), &m); err != nil {
t.Errorf("no error: %v", err)
}
- if strings.TrimSpace(m.ModTime) == "" || m.Path != "test/test/abc" {
+ if len(m.ModTime) < 20 || m.Path != "test/test/abc" {
t.Errorf("invalid json: %v", m)
}
}
@@ -208,35 +201,31 @@ func TestSetModTime(t *testing.T) {
tr := fullSetup(t, false)
os.Setenv("LOCKBOX_SET_MODTIME", testDateTime)
tr.Insert("test/xyz", "test")
- q, err := fullSetup(t, true).Get("test/xyz", backend.HashedValue)
+ q, err := fullSetup(t, true).Get("test/xyz", backend.JSONValue)
if err != nil {
t.Errorf("no error: %v", err)
}
- hash := strings.TrimSpace(q.Value)
- parts := strings.Split(hash, "\n")
- if len(parts) != 2 {
- t.Errorf("invalid hash output: %v", parts)
+ m := backend.JSON{}
+ if err := json.Unmarshal([]byte(q.Value), &m); err != nil {
+ t.Errorf("no error: %v", err)
}
- dt := parts[0]
- if dt != fmt.Sprintf("modtime: %s", testDateTime) {
- t.Errorf("invalid date/time: %s", dt)
+ if m.ModTime != testDateTime {
+ t.Errorf("invalid date/time")
}
tr = fullSetup(t, false)
os.Setenv("LOCKBOX_SET_MODTIME", "")
tr.Insert("test/xyz", "test")
- q, err = fullSetup(t, true).Get("test/xyz", backend.HashedValue)
+ q, err = fullSetup(t, true).Get("test/xyz", backend.JSONValue)
if err != nil {
t.Errorf("no error: %v", err)
}
- hash = strings.TrimSpace(q.Value)
- parts = strings.Split(hash, "\n")
- if len(parts) != 2 {
- t.Errorf("invalid hash output: %v", parts)
+ m = backend.JSON{}
+ if err := json.Unmarshal([]byte(q.Value), &m); err != nil {
+ t.Errorf("no error: %v", err)
}
- dt = parts[0]
- if dt == fmt.Sprintf("modtime: %s", testDateTime) {
- t.Errorf("invalid date/time: %s", dt)
+ if m.ModTime == testDateTime {
+ t.Errorf("invalid date/time")
}
tr = fullSetup(t, false)
diff --git a/internal/backend/types.go b/internal/backend/types.go
@@ -55,8 +55,9 @@ type (
}
// JSON is an entry as a JSON string
JSON struct {
- ModTime string `json:"modtime"`
Path string `json:"path"`
+ ModTime string `json:"modtime"`
+ Hash string `json:"hash"`
}
)
@@ -90,12 +91,8 @@ const (
const (
// BlankValue will not decrypt secrets, empty value
BlankValue ValueMode = iota
- // HashedValue will decrypt and then hash the password
- HashedValue
// SecretValue will have the raw secret onboard
SecretValue
- // StatsValue will show the last modification time
- StatsValue
// JSONValue will show entries as a JSON payload
JSONValue
)
@@ -107,7 +104,7 @@ const (
pathSep = "/"
isGlob = pathSep + "*"
modTimeKey = "ModTime"
- // ModTimeField is the stats field for modification time
+ // ModTimeField is the field for modification time
ModTimeField = "modtime:"
)
diff --git a/internal/cli/completions.bash b/internal/cli/completions.bash
@@ -31,7 +31,7 @@ _{{ $.Executable }}() {
{{- end}}
;;
{{- end}}
- "{{ $.ShowCommand }}" | "{{ $.StatsCommand }}" {{ if not $.ReadOnly }}| "{{ $.RemoveCommand }}" {{end}} {{ if $.CanClip }} | "{{ $.ClipCommand }}" {{end}})
+ "{{ $.ShowCommand }}" | "{{ $.JSONCommand }}" {{ if not $.ReadOnly }}| "{{ $.RemoveCommand }}" {{end}} {{ if $.CanClip }} | "{{ $.ClipCommand }}" {{end}})
opts=$({{ $.DoList }})
;;
esac
diff --git a/internal/cli/core.go b/internal/cli/core.go
@@ -15,8 +15,6 @@ import (
)
const (
- // StatsCommand will display additional entry stat information
- StatsCommand = "stats"
// TOTPCommand is the parent of totp and by defaults generates a rotating token
TOTPCommand = "totp"
// ConvCommand handles text conversion of the data store
@@ -67,6 +65,8 @@ const (
TOTPShowCommand = ShowCommand
// TOTPInsertCommand is for inserting totp tokens
TOTPInsertCommand = InsertCommand
+ // JSONCommand handles JSON outputs
+ JSONCommand = "json"
)
var (
@@ -96,7 +96,7 @@ type (
DoTOTPList string
DoList string
Executable string
- StatsCommand string
+ JSONCommand string
HelpCommand string
HelpAdvancedCommand string
}
@@ -141,14 +141,14 @@ func BashCompletions(defaults bool) ([]string, error) {
ClipCommand: ClipCommand,
ShowCommand: ShowCommand,
MultiLineCommand: MultiLineCommand,
- StatsCommand: StatsCommand,
+ JSONCommand: JSONCommand,
HelpCommand: HelpCommand,
HelpAdvancedCommand: HelpAdvancedCommand,
TOTPCommand: TOTPCommand,
MoveCommand: MoveCommand,
DoList: fmt.Sprintf("%s %s", name, ListCommand),
DoTOTPList: fmt.Sprintf("%s %s %s", name, TOTPCommand, TOTPListCommand),
- Options: []string{MultiLineCommand, EnvCommand, HelpCommand, ListCommand, ShowCommand, VersionCommand, StatsCommand},
+ Options: []string{MultiLineCommand, EnvCommand, HelpCommand, ListCommand, ShowCommand, VersionCommand, JSONCommand},
}
isReadOnly := false
isClip := true
@@ -213,12 +213,12 @@ func Usage(verbose bool) ([]string, error) {
results = append(results, command(HelpCommand, "", "show this usage information"))
results = append(results, subCommand(HelpCommand, HelpAdvancedCommand, "", "display verbose help information"))
results = append(results, command(InsertCommand, "entry", "insert a new entry into the store"))
+ results = append(results, command(JSONCommand, "", "display detailed information"))
results = append(results, command(ListCommand, "", "list entries"))
results = append(results, command(MoveCommand, "src dst", "move an entry from source to destination"))
results = append(results, command(MultiLineCommand, "entry", "insert a multiline entry into the store"))
results = append(results, command(RemoveCommand, "entry", "remove an entry from the store"))
results = append(results, command(ShowCommand, "entry", "show the entry's value"))
- results = append(results, command(StatsCommand, "entry", "display entry detail information"))
results = append(results, command(TOTPCommand, "entry", "display an updating totp generated code"))
results = append(results, subCommand(TOTPCommand, TOTPClipCommand, "entry", "copy totp code to clipboard"))
results = append(results, subCommand(TOTPCommand, TOTPInsertCommand, "entry", "insert a new totp entry into the store"))
diff --git a/tests/expected.log b/tests/expected.log
@@ -12,31 +12,63 @@ keys2/k/three
key/a/one
keys/k/one2
keys2/k/three
+[
+{
+ "path": "key/a/one",
+ "modtime": "XXXX-XX-XX",
+ "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"
+}
+,
+{
+ "path": "keys/k/one2",
+ "modtime": "XXXX-XX-XX",
+ "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9"
+}
+,
+{
+ "path": "keys2/k/three",
+ "modtime": "XXXX-XX-XX",
+ "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f"
+}
+]
test2
test3
test4
-modtime: XXXX-XX-XX
+{
+ "path": "keys2/k/three",
+ "modtime": "XXXX-XX-XX",
+ "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f"
+}
+
test/k
XXXXXX
XXXXXX
XXXXXX
-key/a/one:
- modtime: XXXX-XX-XX
- hash: ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff
-
-keys/k/one2:
- modtime: XXXX-XX-XX
- hash: 6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9
-
-keys2/k/three:
- modtime: XXXX-XX-XX
- hash: 132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f
-
-test/k/totp:
- modtime: XXXX-XX-XX
- hash: 7ef183065ba70aaa417b87ea0a96b7e550a938a52440c640a07537f7794d8a89e50078eca6a7cbcfacabd97a2db06d11e82ddf7556ca909c4df9fc0d006013b1
-
-delete entry? (y/N)
+[
+{
+ "path": "key/a/one",
+ "modtime": "XXXX-XX-XX",
+ "hash": "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"
+}
+,
+{
+ "path": "keys/k/one2",
+ "modtime": "XXXX-XX-XX",
+ "hash": "6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca003257b5e8f31bdc1d73fbec84fb085c79d6e2677b7ff927e823a54e789140d9"
+}
+,
+{
+ "path": "keys2/k/three",
+ "modtime": "XXXX-XX-XX",
+ "hash": "132ab0244293c495a027cec12d0050598616daca888449920fc652719be0987830827d069ef78cc613e348de37c9b592d3406e2fb8d99a6961bf0c58da8a334f"
+}
+,
+{
+ "path": "test/k/totp",
+ "modtime": "XXXX-XX-XX",
+ "hash": "7ef183065ba70aaa417b87ea0a96b7e550a938a52440c640a07537f7794d8a89e50078eca6a7cbcfacabd97a2db06d11e82ddf7556ca909c4df9fc0d006013b1"
+}
+]delete entry? (y/N)
delete entry? (y/N)
delete entry? (y/N) unable to remove: no entities given
diff --git a/tests/run.sh b/tests/run.sh
@@ -28,9 +28,12 @@ _execute() {
echo
${LB_BINARY} ls
${LB_BINARY} ls | grep e
+ ${LB_BINARY} json
+ echo
${LB_BINARY} show keys/k/one2
${LB_BINARY} show keys2/k/three
- ${LB_BINARY} stats keys2/k/three
+ ${LB_BINARY} json keys2/k/three
+ echo
echo 5ae472abqdekjqykoyxk7hvc2leklq5n |${LB_BINARY} totp insert test/k
echo 5ae472abqdekjqykoyxk7hvc2leklq5n |${LB_BINARY} totp insert test/k/totp
${LB_BINARY} totp ls
@@ -121,7 +124,7 @@ _clipboard() {
_logtest() {
_execute 2>&1 | \
- sed 's/modtime: [0-9].*$/modtime: XXXX-XX-XX/g' | \
+ sed 's/"modtime": "[0-9].*$/"modtime": "XXXX-XX-XX",/g' | \
sed 's/^[0-9][0-9][0-9][0-9][0-9][0-9]$/XXXXXX/g'
}