diff --git a/cmd/restic/cmd_cache.go b/cmd/restic/cmd_cache.go index 1f19a40f2..f206dc845 100644 --- a/cmd/restic/cmd_cache.go +++ b/cmd/restic/cmd_cache.go @@ -9,6 +9,7 @@ import ( "github.com/restic/restic/internal/cache" "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/fs" + "github.com/restic/restic/internal/ui/table" "github.com/spf13/cobra" ) @@ -85,9 +86,17 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error { return nil } - tab := NewTable() - tab.Header = fmt.Sprintf("%-14s %-16s %s", "Repository ID", "Last Used", "Old") - tab.RowFormat = "%-14s %-16s %s" + tab := table.New() + + type data struct { + ID string + Last string + Old string + } + + tab.AddColumn("Repo ID", "{{ .ID }}") + tab.AddColumn("Last Used", "{{ .Last }}") + tab.AddColumn("Old", "{{ .Old }}") dirs, err := cache.All(cachedir) if err != nil { @@ -109,7 +118,7 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error { old = "yes" } - tab.Rows = append(tab.Rows, []interface{}{ + tab.AddRow(data{ entry.Name()[:10], fmt.Sprintf("%d days ago", uint(time.Since(entry.ModTime()).Hours()/24)), old, diff --git a/cmd/restic/cmd_key.go b/cmd/restic/cmd_key.go index 0c5a7e9a0..900b29d50 100644 --- a/cmd/restic/cmd_key.go +++ b/cmd/restic/cmd_key.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "fmt" "io/ioutil" "os" "strings" @@ -11,6 +10,7 @@ import ( "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/restic" + "github.com/restic/restic/internal/ui/table" "github.com/spf13/cobra" ) @@ -36,53 +36,18 @@ func init() { flags.StringVarP(&newPasswordFile, "new-password-file", "", "", "the file from which to load a new password") } -type keyInfo struct { - Current bool `json:"current"` - ID string `json:"id"` - UserName string `json:"userName"` - HostName string `json:"hostName"` - Created string `json:"created"` -} - -func (ki keyInfo) CurrentStr() string { - if ki.Current { - return "*" - } - return " " -} - func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions) error { - var ( - appendKey func(keyInfo) - printKeys func() error - ) - - switch gopts.JSON { - case true: - var keys []keyInfo - - appendKey = func(key keyInfo) { - keys = append(keys, key) - } - - printKeys = func() error { - return json.NewEncoder(gopts.stdout).Encode(keys) - } - default: - tab := NewTable() - tab.Header = fmt.Sprintf(" %-10s %-10s %-10s %s", "ID", "User", "Host", "Created") - tab.RowFormat = "%s%-10s %-10s %-10s %s" - - appendKey = func(key keyInfo) { - tab.Rows = append(tab.Rows, []interface{}{key.CurrentStr(), key.ID, key.UserName, key.HostName, key.Created}) - } - - printKeys = func() error { - return tab.Write(globalOptions.stdout) - } + type keyInfo struct { + Current bool `json:"current"` + ID string `json:"id"` + UserName string `json:"userName"` + HostName string `json:"hostName"` + Created string `json:"created"` } - if err := s.List(ctx, restic.KeyFile, func(id restic.ID, size int64) error { + var keys []keyInfo + + err := s.List(ctx, restic.KeyFile, func(id restic.ID, size int64) error { k, err := repository.LoadKey(ctx, s, id.String()) if err != nil { Warnf("LoadKey() failed: %v\n", err) @@ -97,14 +62,29 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions Created: k.Created.Format(TimeFormat), } - appendKey(key) - + keys = append(keys, key) return nil - }); err != nil { + }) + + if err != nil { return err } - return printKeys() + if gopts.JSON { + return json.NewEncoder(globalOptions.stdout).Encode(keys) + } + + tab := table.New() + tab.AddColumn(" ID", "{{if .Current}}*{{else}} {{end}}{{ .ID }}") + tab.AddColumn("User", "{{ .UserName }}") + tab.AddColumn("Host", "{{ .HostName }}") + tab.AddColumn("Created", "{{ .Created }}") + + for _, key := range keys { + tab.AddRow(key) + } + + return tab.Write(globalOptions.stdout) } // testKeyNewPassword is used to set a new password during integration testing. diff --git a/cmd/restic/global.go b/cmd/restic/global.go index d35b6ba4f..e288fb2da 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -38,6 +38,9 @@ import ( var version = "0.9.2-dev (compiled manually)" +// TimeFormat is the format used for all timestamps printed by restic. +const TimeFormat = "2006-01-02 15:04:05" + // GlobalOptions hold all global options for restic. type GlobalOptions struct { Repo string diff --git a/cmd/restic/table.go b/cmd/restic/table.go deleted file mode 100644 index b2fa772f8..000000000 --- a/cmd/restic/table.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "fmt" - "io" - "strings" -) - -// Table contains data for a table to be printed. -type Table struct { - Header string - Rows [][]interface{} - Footer string - - RowFormat string -} - -// NewTable initializes a new Table. -func NewTable() Table { - return Table{ - Rows: [][]interface{}{}, - } -} - -func (t Table) printSeparationLine(w io.Writer) error { - _, err := fmt.Fprintln(w, strings.Repeat("-", 70)) - return err -} - -// Write prints the table to w. -func (t Table) Write(w io.Writer) error { - _, err := fmt.Fprintln(w, t.Header) - if err != nil { - return err - } - - err = t.printSeparationLine(w) - if err != nil { - return err - } - - for _, row := range t.Rows { - _, err = fmt.Fprintf(w, t.RowFormat+"\n", row...) - if err != nil { - return err - } - } - - err = t.printSeparationLine(w) - if err != nil { - return err - } - - _, err = fmt.Fprintln(w, t.Footer) - if err != nil { - return err - } - - return nil -} - -// TimeFormat is the format used for all timestamps printed by restic. -const TimeFormat = "2006-01-02 15:04:05"