Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

command buckets converted to the cobra style #859

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions cmd/bbolt/command_buckets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"fmt"

"github.com/spf13/cobra"
bolt "go.etcd.io/bbolt"
)

func newBucketsCommand() *cobra.Command {
var bucketsCmd = &cobra.Command{
Use: "buckets <path>",
Short: "print a list of buckets",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return bucketsFunc(cmd, args[0])
},
}
return bucketsCmd
}

func bucketsFunc(cmd *cobra.Command, srcDBPath string) error {
// Required database path.
if _, err := checkSourceDBPath(srcDBPath); err != nil {
return err
}

// Open database.
db, err := bolt.Open(srcDBPath, 0600, &bolt.Options{ReadOnly: true})
if err != nil {
return err
}
defer db.Close()

// Print the list of buckets in the database.
return db.View(func(tx *bolt.Tx) error {
return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
fmt.Fprintln(cmd.OutOrStdout(), string(name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that cmd.OutOrStdout() is a little better than os.Stdout, but please keep it consistent with other commands. We can replace them with cmd.OutOrStdout() in separate PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd.OutOrStdout() is all ready used in the cobra style converted files already
command_check.go line 44, 65, 70
command_get.go line 46, 92
command_info.go line 47
command_version.go line 18, 19, 20

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that it's only used in command_check.go. I should have raised this comment in PR 723.

Overall, not a big deal. Feel free to keep it as it's

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have changed the over files in my copy above when I was testing the outputs.
As I had trouble capturing the output when I had converted to the cobra style without the cmd.OutOrStdout() function

return nil
})
})
}
48 changes: 48 additions & 0 deletions cmd/bbolt/command_buckets_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main_test

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"

bolt "go.etcd.io/bbolt"
main "go.etcd.io/bbolt/cmd/bbolt"
"go.etcd.io/bbolt/internal/btesting"
)

// Ensure the "buckets" command can print a list of buckets.
func TestBuckets(t *testing.T) {
// Create a test database and populate it with sample buckets.
t.Log("Creating sample DB")
db := btesting.MustCreateDB(t)
t.Log("Creating sample Buckets")
if err := db.Update(func(tx *bolt.Tx) error {
for _, name := range []string{"foo", "bar", "baz"} {
_, err := tx.CreateBucket([]byte(name))
if err != nil {
return err
}
}
return nil
}); err != nil {
t.Fatal(err)
}
db.Close()
defer requireDBNoChange(t, dbData(t, db.Path()), db.Path())

// setup the buckets command.
t.Log("Running buckets command")
rootCmd := main.NewRootCommand()
var args []string = []string{"buckets", db.Path()}
outputBuf := bytes.NewBufferString("")
rootCmd.SetOut(outputBuf)
rootCmd.SetErr(outputBuf)
rootCmd.SetArgs(args)
_, err := rootCmd.ExecuteC()
actualOutput := outputBuf.String()
require.NoError(t, err)
t.Log("Verify result")
expected := "bar\nbaz\nfoo\n"
require.EqualValues(t, expected, actualOutput)
}
1 change: 1 addition & 0 deletions cmd/bbolt/command_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func NewRootCommand() *cobra.Command {
newSurgeryCommand(),
newInspectCommand(),
newCheckCommand(),
newBucketsCommand(),
)

return rootCmd
Expand Down
59 changes: 0 additions & 59 deletions cmd/bbolt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ func (m *Main) Run(args ...string) error {
return ErrUsage
case "bench":
return newBenchCommand(m).Run(args[1:]...)
case "buckets":
return newBucketsCommand(m).Run(args[1:]...)
case "compact":
return newCompactCommand(m).Run(args[1:]...)
case "dump":
Expand Down Expand Up @@ -763,63 +761,6 @@ experience corruption, please submit a ticket to the etcd-io/bbolt project page:
`, "\n")
}

// bucketsCommand represents the "buckets" command execution.
type bucketsCommand struct {
baseCommand
}

// newBucketsCommand returns a bucketsCommand.
func newBucketsCommand(m *Main) *bucketsCommand {
c := &bucketsCommand{}
c.baseCommand = m.baseCommand
return c
}

// Run executes the command.
func (cmd *bucketsCommand) Run(args ...string) error {
// Parse flags.
fs := flag.NewFlagSet("", flag.ContinueOnError)
help := fs.Bool("h", false, "")
if err := fs.Parse(args); err != nil {
return err
} else if *help {
fmt.Fprintln(cmd.Stderr, cmd.Usage())
return ErrUsage
}

// Require database path.
path := fs.Arg(0)
if path == "" {
return ErrPathRequired
} else if _, err := os.Stat(path); os.IsNotExist(err) {
return ErrFileNotFound
}

// Open database.
db, err := bolt.Open(path, 0600, &bolt.Options{ReadOnly: true})
if err != nil {
return err
}
defer db.Close()

// Print buckets.
return db.View(func(tx *bolt.Tx) error {
return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
fmt.Fprintln(cmd.Stdout, string(name))
return nil
})
})
}

// Usage returns the help message.
func (cmd *bucketsCommand) Usage() string {
return strings.TrimLeft(`
usage: bolt buckets PATH

Print a list of buckets.
`, "\n")
}

// keysCommand represents the "keys" command execution.
type keysCommand struct {
baseCommand
Expand Down
30 changes: 0 additions & 30 deletions cmd/bbolt/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,36 +274,6 @@ func TestStatsCommand_Run(t *testing.T) {
}
}

// Ensure the "buckets" command can print a list of buckets.
func TestBucketsCommand_Run(t *testing.T) {
db := btesting.MustCreateDB(t)

if err := db.Update(func(tx *bolt.Tx) error {
for _, name := range []string{"foo", "bar", "baz"} {
_, err := tx.CreateBucket([]byte(name))
if err != nil {
return err
}
}
return nil
}); err != nil {
t.Fatal(err)
}
db.Close()

defer requireDBNoChange(t, dbData(t, db.Path()), db.Path())

expected := "bar\nbaz\nfoo\n"

// Run the command.
m := NewMain()
if err := m.Run("buckets", db.Path()); err != nil {
t.Fatal(err)
} else if actual := m.Stdout.String(); actual != expected {
t.Fatalf("unexpected stdout:\n\n%s", actual)
}
}

// Ensure the "keys" command can print a list of keys for a bucket.
func TestKeysCommand_Run(t *testing.T) {
testCases := []struct {
Expand Down