CMD: add cobra style 'surgery clear-page-elements' command

Signed-off-by: Benjamin Wang <wachao@vmware.com>
pull/417/head
Benjamin Wang 2023-03-19 09:18:53 +08:00
parent 9832aff38a
commit 3c3da590b1
5 changed files with 123 additions and 1 deletions

24
cmd/bbolt/command_root.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"github.com/spf13/cobra"
)
const (
cliName = "bbolt"
cliDescription = "A simple command line tool for inspecting bbolt databases"
)
func NewRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: cliName,
Short: cliDescription,
Version: "dev",
}
rootCmd.AddCommand(
newSurgeryCobraCommand(),
)
return rootCmd
}

View File

@ -0,0 +1,74 @@
package main
import (
"errors"
"fmt"
"os"
"github.com/spf13/cobra"
"go.etcd.io/bbolt/internal/common"
"go.etcd.io/bbolt/internal/surgeon"
)
var (
surgeryTargetDBFilePath string
surgeryPageId uint64
surgeryStartElementIdx int
surgeryEndElementIdx int
)
func newSurgeryCobraCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "surgery <subcommand>",
Short: "surgery related commands",
}
cmd.AddCommand(newSurgeryClearPageElementsCommand())
return cmd
}
func newSurgeryClearPageElementsCommand() *cobra.Command {
clearElementCmd := &cobra.Command{
Use: "clear-page-elements [options]",
Short: "Clears elements from the given page",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("db file path not provided")
}
if len(args) > 1 {
return errors.New("too many arguments")
}
return nil
},
RunE: surgeryClearPageElementFunc,
}
clearElementCmd.Flags().StringVar(&surgeryTargetDBFilePath, "output", "", "path to the target db file")
clearElementCmd.Flags().Uint64VarP(&surgeryPageId, "pageId", "", 0, "page id")
clearElementCmd.Flags().IntVarP(&surgeryStartElementIdx, "from", "", 0, "start element index (included) to clear, starting from 0")
clearElementCmd.Flags().IntVarP(&surgeryEndElementIdx, "to", "", 0, "end element index (excluded) to clear, starting from 0, -1 means to the end of page")
return clearElementCmd
}
func surgeryClearPageElementFunc(cmd *cobra.Command, args []string) error {
srcDBPath := args[0]
if err := copyFile(srcDBPath, surgeryTargetDBFilePath); err != nil {
return fmt.Errorf("[clear-page-element] copy file failed: %w", err)
}
if surgeryPageId < 2 {
return fmt.Errorf("the pageId must be at least 2, but got %d", surgeryPageId)
}
if err := surgeon.ClearPageElements(surgeryTargetDBFilePath, common.Pgid(surgeryPageId), surgeryStartElementIdx, surgeryEndElementIdx); err != nil {
return fmt.Errorf("clear-page-element command failed: %w", err)
}
fmt.Fprintf(os.Stdout, "All elements in [%d, %d) in page %d were cleared\n", surgeryStartElementIdx, surgeryEndElementIdx, surgeryPageId)
return nil
}

View File

@ -60,12 +60,26 @@ func main() {
m := NewMain()
if err := m.Run(os.Args[1:]...); err == ErrUsage {
os.Exit(2)
} else if err == ErrUnknownCommand {
execute()
} else if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
}
func execute() {
rootCmd := NewRootCommand()
if err := rootCmd.Execute(); err != nil {
if rootCmd.SilenceErrors {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
} else {
os.Exit(1)
}
}
}
type baseCommand struct {
Stdin io.Reader
Stdout io.Writer

3
go.mod
View File

@ -3,6 +3,7 @@ module go.etcd.io/bbolt
go 1.19
require (
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.2
go.etcd.io/gofail v0.1.0
golang.org/x/sys v0.6.0
@ -10,6 +11,8 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

9
go.sum
View File

@ -1,14 +1,21 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg=