restic/cmd/restic/main.go

130 lines
3.1 KiB
Go
Raw Normal View History

2014-04-27 22:00:15 +00:00
package main
import (
"bufio"
"bytes"
2015-07-12 20:10:01 +00:00
"fmt"
"log"
"os"
2017-06-11 12:17:44 +00:00
"runtime"
2017-07-23 12:21:03 +00:00
"github.com/restic/restic/internal/debug"
"github.com/restic/restic/internal/options"
2017-07-24 15:42:25 +00:00
"github.com/restic/restic/internal/restic"
2017-07-23 12:21:03 +00:00
2016-09-17 10:36:05 +00:00
"github.com/spf13/cobra"
2016-09-01 20:17:37 +00:00
2017-07-23 12:21:03 +00:00
"github.com/restic/restic/internal/errors"
2014-04-27 22:00:15 +00:00
)
2016-09-17 10:36:05 +00:00
// cmdRoot is the base command when no other command has been specified.
var cmdRoot = &cobra.Command{
Use: "restic",
Short: "Backup and restore files",
2016-09-17 10:36:05 +00:00
Long: `
restic is a backup program which allows saving multiple revisions of files and
directories in an encrypted repository stored on different backends.
`,
SilenceErrors: true,
SilenceUsage: true,
DisableAutoGenTag: true,
2017-01-22 18:10:32 +00:00
PersistentPreRunE: func(c *cobra.Command, args []string) error {
2018-04-22 09:57:20 +00:00
// set verbosity, default is one
2018-04-21 20:07:14 +00:00
globalOptions.verbosity = 1
if globalOptions.Quiet && globalOptions.Verbose > 0 {
2018-04-22 09:57:20 +00:00
return errors.Fatal("--quiet and --verbose cannot be specified at the same time")
2018-04-21 20:07:14 +00:00
}
switch {
2018-04-22 09:57:20 +00:00
case globalOptions.Verbose >= 2:
globalOptions.verbosity = 3
case globalOptions.Verbose > 0:
globalOptions.verbosity = 2
2018-04-21 20:07:14 +00:00
case globalOptions.Quiet:
globalOptions.verbosity = 0
}
2017-03-25 14:33:52 +00:00
// parse extended options
opts, err := options.Parse(globalOptions.Options)
if err != nil {
return err
}
globalOptions.extended = opts
if !needsPassword(c.Name()) {
return nil
}
pwd, err := resolvePassword(globalOptions, "RESTIC_PASSWORD")
if err != nil {
fmt.Fprintf(os.Stderr, "Resolving password failed: %v\n", err)
Exit(1)
}
globalOptions.password = pwd
2017-03-25 14:33:52 +00:00
// run the debug functions for all subcommands (if build tag "debug" is
// enabled)
if err := runDebug(); err != nil {
return err
}
return nil
},
2016-09-17 10:36:05 +00:00
}
// Distinguish commands that need the password from those that work without,
// so we don't run $RESTIC_PASSWORD_COMMAND for no reason (it might prompt the
// user for authentication).
func needsPassword(cmd string) bool {
switch cmd {
case "cache", "generate", "help", "options", "self-update", "version":
return false
default:
return true
}
}
var logBuffer = bytes.NewBuffer(nil)
func init() {
// install custom global logger into a buffer, if an error occurs
// we can show the logs
log.SetOutput(logBuffer)
}
2014-04-27 22:00:15 +00:00
func main() {
2016-09-27 20:35:08 +00:00
debug.Log("main %#v", os.Args)
2018-03-21 20:49:03 +00:00
debug.Log("restic %s compiled with %v on %v/%v",
2017-06-11 12:17:44 +00:00
version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
2022-10-02 21:24:37 +00:00
err := cmdRoot.ExecuteContext(internalGlobalCtx)
switch {
case restic.IsAlreadyLocked(err):
fmt.Fprintf(os.Stderr, "%v\nthe `unlock` command can be used to remove stale locks\n", err)
case err == ErrInvalidSourceData:
fmt.Fprintf(os.Stderr, "Warning: %v\n", err)
case errors.IsFatal(err):
fmt.Fprintf(os.Stderr, "%v\n", err)
case err != nil:
2016-08-21 16:07:13 +00:00
fmt.Fprintf(os.Stderr, "%+v\n", err)
if logBuffer.Len() > 0 {
fmt.Fprintf(os.Stderr, "also, the following messages were logged by a library:\n")
sc := bufio.NewScanner(logBuffer)
for sc.Scan() {
fmt.Fprintln(os.Stderr, sc.Text())
}
}
2016-01-17 15:59:03 +00:00
}
var exitCode int
switch err {
case nil:
exitCode = 0
case ErrInvalidSourceData:
exitCode = 3
default:
exitCode = 1
2014-04-27 22:00:15 +00:00
}
Exit(exitCode)
2014-04-27 22:00:15 +00:00
}