diff --git a/cmd/bbolt/command_info.go b/cmd/bbolt/command_info.go new file mode 100644 index 000000000..2e26659d1 --- /dev/null +++ b/cmd/bbolt/command_info.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + bolt "go.etcd.io/bbolt" +) // infoCommand represents the "info" command execution. +type infoCommand struct { + baseCommand +} + +// newInfoCommand returns a infoCommand. +func newInfoCommand() *cobra.Command { + var infoCmd = &cobra.Command{ + Use: "info ", + Short: "Info prints basic information about the Bolt database at PATH.", + Long: "Info prints basic information about the Bolt database at PATH.", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return info(cmd, args[0]) + }, + } + return infoCmd +} + +// Run executes the command. +func info(cmd *cobra.Command, path string) error { + + // Require database path. + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Open the database. + db, err := bolt.Open(path, 0600, &bolt.Options{ReadOnly: true}) + if err != nil { + return err + } + defer db.Close() + + // Print basic database info. + info := db.Info() + fmt.Fprintf(cmd.OutOrStdout(), "Page Size: %d\n", info.PageSize) + + return nil +} diff --git a/cmd/bbolt/command_info_test.go b/cmd/bbolt/command_info_test.go new file mode 100644 index 000000000..431f97580 --- /dev/null +++ b/cmd/bbolt/command_info_test.go @@ -0,0 +1,32 @@ +package main_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + main "go.etcd.io/bbolt/cmd/bbolt" + "go.etcd.io/bbolt/internal/btesting" +) + +// Ensure the "info" command can print information about a database. +// +// This test case verifies that the "info" command can print information about a +// database. It checks that the output of the command matches the expected result. +func TestInfoCommand_Run(t *testing.T) { + // Create a test database. + db := btesting.MustCreateDB(t) + db.Close() + + defer requireDBNoChange(t, dbData(t, db.Path()), db.Path()) + + // Run the info command. + t.Log("Running info command") + rootCmd := main.NewRootCommand() + _, actualOutput, err := executeCommand(rootCmd, "info", db.Path()) + require.NoError(t, err) + + // check results + t.Log("Verify result") + expected := "Page Size: 4096\n" + require.EqualValues(t, expected, actualOutput) +} diff --git a/cmd/bbolt/command_root.go b/cmd/bbolt/command_root.go index a278458b7..d7ed53bb4 100644 --- a/cmd/bbolt/command_root.go +++ b/cmd/bbolt/command_root.go @@ -22,6 +22,7 @@ func NewRootCommand() *cobra.Command { newInspectCommand(), newCheckCommand(), newBucketsCommand(), + newInfoCommand(), ) return rootCmd diff --git a/cmd/bbolt/main.go b/cmd/bbolt/main.go index b934b9900..1a93f2b2b 100644 --- a/cmd/bbolt/main.go +++ b/cmd/bbolt/main.go @@ -130,8 +130,6 @@ func (m *Main) Run(args ...string) error { return newPageItemCommand(m).Run(args[1:]...) case "get": return newGetCommand(m).Run(args[1:]...) - case "info": - return newInfoCommand(m).Run(args[1:]...) case "keys": return newKeysCommand(m).Run(args[1:]...) case "page": @@ -177,61 +175,6 @@ Use "bbolt [command] -h" for more information about a command. `, "\n") } -// infoCommand represents the "info" command execution. -type infoCommand struct { - baseCommand -} - -// newInfoCommand returns a infoCommand. -func newInfoCommand(m *Main) *infoCommand { - c := &infoCommand{} - c.baseCommand = m.baseCommand - return c -} - -// Run executes the command. -func (cmd *infoCommand) 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 the database. - db, err := bolt.Open(path, 0600, &bolt.Options{ReadOnly: true}) - if err != nil { - return err - } - defer db.Close() - - // Print basic database info. - info := db.Info() - fmt.Fprintf(cmd.Stdout, "Page Size: %d\n", info.PageSize) - - return nil -} - -// Usage returns the help message. -func (cmd *infoCommand) Usage() string { - return strings.TrimLeft(` -usage: bolt info PATH - -Info prints basic information about the Bolt database at PATH. -`, "\n") -} - // dumpCommand represents the "dump" command execution. type dumpCommand struct { baseCommand diff --git a/cmd/bbolt/main_test.go b/cmd/bbolt/main_test.go index ef2b6f78e..57d15d7e3 100644 --- a/cmd/bbolt/main_test.go +++ b/cmd/bbolt/main_test.go @@ -24,20 +24,6 @@ import ( main "go.etcd.io/bbolt/cmd/bbolt" ) -// Ensure the "info" command can print information about a database. -func TestInfoCommand_Run(t *testing.T) { - db := btesting.MustCreateDB(t) - db.Close() - - defer requireDBNoChange(t, dbData(t, db.Path()), db.Path()) - - // Run the info command. - m := NewMain() - if err := m.Run("info", db.Path()); err != nil { - t.Fatal(err) - } -} - // Ensure the "stats" command executes correctly with an empty database. func TestStatsCommand_Run_EmptyDatabase(t *testing.T) { // Ignore