diff --git a/cmd/restic/global.go b/cmd/restic/global.go index 2c73da530..5d9875fce 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -21,11 +21,13 @@ import ( var version = "compiled manually" var compiledAt = "unknown time" +// GlobalOptions holds all those options that can be set for every command. type GlobalOptions struct { - Repo string `short:"r" long:"repo" description:"Repository directory to backup to/restore from"` - CacheDir string ` long:"cache-dir" description:"Directory to use as a local cache"` - Quiet bool `short:"q" long:"quiet" default:"false" description:"Do not output comprehensive progress report"` - NoLock bool ` long:"no-lock" default:"false" description:"Do not lock the repo, this allows some operations on read-only repos."` + Repo string `short:"r" long:"repo" description:"Repository directory to backup to/restore from"` + CacheDir string ` long:"cache-dir" description:"Directory to use as a local cache"` + Quiet bool `short:"q" long:"quiet" default:"false" description:"Do not output comprehensive progress report"` + NoLock bool ` long:"no-lock" default:"false" description:"Do not lock the repo, this allows some operations on read-only repos."` + Options []string `short:"o" long:"option" description:"Specify options in the form 'foo.key=value'"` password string stdout io.Writer @@ -33,8 +35,9 @@ type GlobalOptions struct { } var globalOpts = GlobalOptions{stdout: os.Stdout, stderr: os.Stderr} -var parser = flags.NewParser(&globalOpts, flags.Default) +var parser = flags.NewParser(&globalOpts, flags.HelpFlag|flags.PassDoubleDash) +// Printf writes the message to the configured stdout stream. func (o GlobalOptions) Printf(format string, args ...interface{}) { _, err := fmt.Fprintf(o.stdout, format, args...) if err != nil { @@ -43,6 +46,7 @@ func (o GlobalOptions) Printf(format string, args ...interface{}) { } } +// Verbosef calls Printf to write the message when the verbose flag is set. func (o GlobalOptions) Verbosef(format string, args ...interface{}) { if o.Quiet { return @@ -51,6 +55,8 @@ func (o GlobalOptions) Verbosef(format string, args ...interface{}) { o.Printf(format, args...) } +// ShowProgress returns true iff the progress status should be written, i.e. +// the quiet flag is not set and the output is a terminal. func (o GlobalOptions) ShowProgress() bool { if o.Quiet { return false @@ -63,6 +69,7 @@ func (o GlobalOptions) ShowProgress() bool { return true } +// Warnf writes the message to the configured stderr stream. func (o GlobalOptions) Warnf(format string, args ...interface{}) { _, err := fmt.Fprintf(o.stderr, format, args...) if err != nil { @@ -71,6 +78,7 @@ func (o GlobalOptions) Warnf(format string, args ...interface{}) { } } +// Exitf uses Warnf to write the message and then calls os.Exit(exitcode). func (o GlobalOptions) Exitf(exitcode int, format string, args ...interface{}) { if format[len(format)-1] != '\n' { format += "\n" @@ -108,6 +116,7 @@ func readPasswordTerminal(in *os.File, out io.Writer, prompt string) (password s return password, nil } +// ReadPassword reads the password from stdin. func (o GlobalOptions) ReadPassword(prompt string) string { var ( password string @@ -131,6 +140,8 @@ func (o GlobalOptions) ReadPassword(prompt string) string { return password } +// ReadPasswordTwice calls ReadPassword two times and returns an error when the +// passwords don't match. func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) string { pw1 := o.ReadPassword(prompt1) pw2 := o.ReadPassword(prompt2) @@ -141,6 +152,7 @@ func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) string { return pw1 } +// OpenRepository reads the password and opens the repository. func (o GlobalOptions) OpenRepository() (*repository.Repository, error) { if o.Repo == "" { return nil, errors.New("Please specify repository location (-r)") diff --git a/cmd/restic/main.go b/cmd/restic/main.go index a11bab84f..32598fe23 100644 --- a/cmd/restic/main.go +++ b/cmd/restic/main.go @@ -25,9 +25,14 @@ func main() { _, err := parser.Parse() if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp { + parser.WriteHelp(os.Stdout) os.Exit(0) } + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + } + if restic.IsAlreadyLocked(err) { fmt.Fprintf(os.Stderr, "\nthe `unlock` command can be used to remove stale locks\n") }