diff --git a/app/db.go b/app/db.go index a21d2f1..254337b 100644 --- a/app/db.go +++ b/app/db.go @@ -49,6 +49,17 @@ type DbEntry struct { Size int } +type BucketInfo struct { + Name string + Keys int + Size int +} + +type DbInfo struct { + Buckets []BucketInfo + Path string +} + // Post process an entry for list output. // Do NOT call it during write processing! func (entry *DbEntry) Normalize() { @@ -77,7 +88,7 @@ type DbTag struct { const BucketData string = "data" func New(file string, bucket string, debug bool) (*DB, error) { - return &DB{Debug: debug, Dbfile: file, Bucket: bucket}, nil + return &DB{Debug: debug, Dbfile: file, Bucket: bucket}, nil } func (db *DB) Open() error { @@ -352,3 +363,34 @@ func (db *DB) Import(attr *DbAttr) (string, error) { return fmt.Sprintf("backed up database file to %s\nimported %d database entries\n", newfile, len(entries)), nil } + +func (db *DB) Info() (*DbInfo, error) { + if err := db.Open(); err != nil { + return nil, err + } + defer db.Close() + + info := &DbInfo{Path: db.Dbfile} + + err := db.DB.View(func(tx *bolt.Tx) error { + tx.ForEach(func(name []byte, bucket *bolt.Bucket) error { + binfo := BucketInfo{Name: string(name)} + err := bucket.ForEach(func(key, entry []byte) error { + binfo.Size += len(entry) + binfo.Keys++ + + return nil + }) + if err != nil { + return err + } + + info.Buckets = append(info.Buckets, binfo) + return nil + + }) + return nil + + }) + return info, err +} diff --git a/cmd/crud.go b/cmd/crud.go index f7c8755..62eb3a6 100644 --- a/cmd/crud.go +++ b/cmd/crud.go @@ -352,3 +352,26 @@ func Serve(conf *cfg.Config) *cobra.Command { return cmd } + +func Info(conf *cfg.Config) *cobra.Command { + var cmd = &cobra.Command{ + Use: "info", + Short: "info", + Long: `show info about database`, + RunE: func(cmd *cobra.Command, args []string) error { + // errors at this stage do not cause the usage to be shown + cmd.SilenceUsage = true + + info, err := conf.DB.Info() + if err != nil { + return err + } + + return output.Info(os.Stdout, conf, info) + }, + } + + cmd.PersistentFlags().StringVarP(&conf.Listen, "listen", "l", "localhost:8787", "host:port") + + return cmd +} diff --git a/cmd/root.go b/cmd/root.go index 61c0afb..efd532c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -93,7 +93,7 @@ func Execute() { rootCmd.PersistentFlags().StringVarP(&conf.Dbfile, "dbfile", "f", filepath.Join(home, ".config", "anydb", "default.db"), "DB file to use") rootCmd.PersistentFlags().StringVarP(&conf.Dbbucket, "bucket", "b", - app.BucketData, "use other bucket (default: " + app.BucketData +")") + app.BucketData, "use other bucket (default: "+app.BucketData+")") rootCmd.AddCommand(Set(&conf)) rootCmd.AddCommand(List(&conf)) @@ -103,6 +103,7 @@ func Execute() { rootCmd.AddCommand(Import(&conf)) rootCmd.AddCommand(Serve(&conf)) rootCmd.AddCommand(Man(&conf)) + rootCmd.AddCommand(Info(&conf)) err = rootCmd.Execute() if err != nil { diff --git a/output/single.go b/output/single.go index 44e8330..6a19e02 100644 --- a/output/single.go +++ b/output/single.go @@ -26,6 +26,7 @@ import ( "github.com/tlinden/anydb/app" "github.com/tlinden/anydb/cfg" "golang.org/x/term" + //"github.com/alecthomas/repr" ) func Print(writer io.Writer, conf *cfg.Config, attr *app.DbAttr, entry *app.DbEntry) error { @@ -93,3 +94,14 @@ func WriteFile(writer io.Writer, conf *cfg.Config, attr *app.DbAttr, entry *app. return nil } + +func Info(writer io.Writer, conf *cfg.Config, info *app.DbInfo) error { + // repr.Println(info) + fmt.Fprintf(writer, "Database: %s\n", info.Path) + + for _, bucket := range info.Buckets { + + fmt.Fprintf(writer, "Bucket: %s\n Size: %d\n Keys: %d\n\n", bucket.Name, bucket.Size, bucket.Keys) + } + return nil +}