From 8fa6531b1cff8288d453dafa656753fb08192aeb Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Fri, 21 Mar 2014 22:05:28 -0600 Subject: [PATCH] Add 'bolt keys'. --- cmd/bolt/main.go | 46 ++++++++++++++++++++++++++++++++++++++++--- cmd/bolt/main_test.go | 32 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/cmd/bolt/main.go b/cmd/bolt/main.go index 0a17a13..c29d5df 100644 --- a/cmd/bolt/main.go +++ b/cmd/bolt/main.go @@ -23,14 +23,19 @@ func NewApp() *cli.App { { Name: "get", Usage: "retrieve a value for given key", - Action: Get, + Action: GetCommand, + }, + { + Name: "keys", + Usage: "retrieve a list of all keys in a bucket", + Action: KeysCommand, }, } return app } -// Get retrieves the value for a given bucket/key. -func Get(c *cli.Context) { +// GetCommand retrieves the value for a given bucket/key. +func GetCommand(c *cli.Context) { path, name, key := c.Args().Get(0), c.Args().Get(1), c.Args().Get(2) if _, err := os.Stat(path); os.IsNotExist(err) { fatal(err) @@ -68,6 +73,41 @@ func Get(c *cli.Context) { } } +// KeysCommand retrieves a list of keys for a given bucket. +func KeysCommand(c *cli.Context) { + path, name := c.Args().Get(0), c.Args().Get(1) + if _, err := os.Stat(path); os.IsNotExist(err) { + fatal(err) + return + } + + db, err := bolt.Open(path, 0600) + if err != nil { + fatal(err) + return + } + defer db.Close() + + err = db.With(func(tx *bolt.Tx) error { + // Find bucket. + b := tx.Bucket(name) + if b == nil { + fatalf("bucket not found: %s", name) + return nil + } + + // Iterate over each key. + return b.ForEach(func(key, _ []byte) error { + logger.Println(string(key)) + return nil + }) + }) + if err != nil { + fatal(err) + return + } +} + var logger = log.New(os.Stderr, "", 0) var logBuffer *bytes.Buffer diff --git a/cmd/bolt/main_test.go b/cmd/bolt/main_test.go index 5c70c97..95b4df5 100644 --- a/cmd/bolt/main_test.go +++ b/cmd/bolt/main_test.go @@ -53,6 +53,38 @@ func TestGetKeyNotFound(t *testing.T) { }) } +// Ensure that a list of keys can be retrieved for a given bucket. +func TestKeys(t *testing.T) { + SetTestMode(true) + open(func(db *bolt.DB) { + db.Do(func(tx *bolt.Tx) error { + tx.CreateBucket("widgets") + tx.Bucket("widgets").Put([]byte("0002"), []byte("")) + tx.Bucket("widgets").Put([]byte("0001"), []byte("")) + tx.Bucket("widgets").Put([]byte("0003"), []byte("")) + return nil + }) + output := run("keys", db.Path(), "widgets") + assert.Equal(t, "0001\n0002\n0003", output) + }) +} + +// Ensure that an error is reported if the database is not found. +func TestKeysDBNotFound(t *testing.T) { + SetTestMode(true) + output := run("keys", "no/such/db", "widgets") + assert.Equal(t, "stat no/such/db: no such file or directory", output) +} + +// Ensure that an error is reported if the bucket is not found. +func TestKeysBucketNotFound(t *testing.T) { + SetTestMode(true) + open(func(db *bolt.DB) { + output := run("keys", db.Path(), "widgets") + assert.Equal(t, "bucket not found: widgets", output) + }) +} + // open creates and opens a Bolt database in the temp directory. func open(fn func(*bolt.DB)) { f, _ := ioutil.TempFile("", "bolt-")