diff --git a/cli/app.go b/cli/app.go index 6bc6b61bb..6aee48a04 100644 --- a/cli/app.go +++ b/cli/app.go @@ -3,7 +3,6 @@ import ( "context" - "fmt" "net/http" "os" "time" @@ -13,6 +12,7 @@ "github.com/kopia/repo" "github.com/kopia/repo/block" "github.com/kopia/repo/storage" + "github.com/pkg/errors" kingpin "gopkg.in/alecthomas/kingpin.v2" ) @@ -76,7 +76,7 @@ func repositoryAction(act func(ctx context.Context, rep *repo.Repository) error) reportSubcommandFinished(kpc.SelectedCommand.FullCommand(), err == nil, storageType, rep.Blocks.Format.Version, commandDuration) if cerr := rep.Close(ctx); cerr != nil { - return fmt.Errorf("unable to close repository: %v", cerr) + return errors.Wrap(cerr, "unable to close repository") } return err } diff --git a/cli/command_block_gc.go b/cli/command_block_gc.go index 544c4f166..d1973f4cb 100644 --- a/cli/command_block_gc.go +++ b/cli/command_block_gc.go @@ -2,9 +2,9 @@ import ( "context" - "fmt" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -15,7 +15,7 @@ func runBlockGarbageCollectAction(ctx context.Context, rep *repo.Repository) error { unused, err := rep.Blocks.FindUnreferencedStorageFiles(ctx) if err != nil { - return fmt.Errorf("error looking for unreferenced storage files: %v", err) + return errors.Wrap(err, "error looking for unreferenced storage files") } if len(unused) == 0 { @@ -37,7 +37,7 @@ func runBlockGarbageCollectAction(ctx context.Context, rep *repo.Repository) err for _, u := range unused { printStderr("Deleting unused block %q (%v bytes)...\n", u.BlockID, u.Length) if err := rep.Storage.DeleteBlock(ctx, u.BlockID); err != nil { - return fmt.Errorf("unable to delete block %q: %v", u.BlockID, err) + return errors.Wrapf(err, "unable to delete block %q", u.BlockID) } } diff --git a/cli/command_block_rewrite.go b/cli/command_block_rewrite.go index ce5309ffa..5200e74c1 100644 --- a/cli/command_block_rewrite.go +++ b/cli/command_block_rewrite.go @@ -8,6 +8,7 @@ "github.com/kopia/repo" "github.com/kopia/repo/block" + "github.com/pkg/errors" ) var ( @@ -121,7 +122,7 @@ func findBlockInfos(ctx context.Context, rep *repo.Repository, ch chan blockInfo func findBlocksWithFormatVersion(ctx context.Context, rep *repo.Repository, ch chan blockInfoOrError, version int) { infos, err := rep.Blocks.ListBlockInfos("", true) if err != nil { - ch <- blockInfoOrError{err: fmt.Errorf("unable to list index blocks: %v", err)} + ch <- blockInfoOrError{err: errors.Wrap(err, "unable to list index blocks")} return } @@ -136,14 +137,14 @@ func findBlocksInShortPacks(ctx context.Context, rep *repo.Repository, ch chan b log.Debugf("listing blocks...") infos, err := rep.Blocks.ListBlockInfos("", true) if err != nil { - ch <- blockInfoOrError{err: fmt.Errorf("unable to list index blocks: %v", err)} + ch <- blockInfoOrError{err: errors.Wrap(err, "unable to list index blocks")} return } log.Debugf("finding blocks in short packs...") shortPackBlocks, err := findShortPackBlocks(infos, threshold) if err != nil { - ch <- blockInfoOrError{err: fmt.Errorf("unable to find short pack blocks: %v", err)} + ch <- blockInfoOrError{err: errors.Wrap(err, "unable to find short pack blocks")} return } log.Debugf("found %v short pack blocks", len(shortPackBlocks)) diff --git a/cli/command_block_verify.go b/cli/command_block_verify.go index de2873994..54483b045 100644 --- a/cli/command_block_verify.go +++ b/cli/command_block_verify.go @@ -5,6 +5,7 @@ "fmt" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -29,7 +30,7 @@ func runVerifyBlockCommand(ctx context.Context, rep *repo.Repository) error { func verifyAllBlocks(ctx context.Context, rep *repo.Repository) error { blockIDs, err := rep.Blocks.ListBlocks("") if err != nil { - return fmt.Errorf("unable to list blocks: %v", err) + return errors.Wrap(err, "unable to list blocks") } var errorCount int diff --git a/cli/command_cache_clear.go b/cli/command_cache_clear.go index d3305569f..cf34cd43c 100644 --- a/cli/command_cache_clear.go +++ b/cli/command_cache_clear.go @@ -2,10 +2,10 @@ import ( "context" - "fmt" "os" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -28,7 +28,7 @@ func runCacheClearCommand(ctx context.Context, rep *repo.Repository) error { return nil } - return fmt.Errorf("caching not enabled") + return errors.New("caching not enabled") } func init() { diff --git a/cli/command_diff.go b/cli/command_diff.go index 25b8a0359..a2eb94c8f 100644 --- a/cli/command_diff.go +++ b/cli/command_diff.go @@ -2,13 +2,13 @@ import ( "context" - "fmt" "os" "strings" "github.com/kopia/kopia/internal/diff" "github.com/kopia/kopia/snapshot/snapshotfs" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -32,7 +32,7 @@ func runDiffCommand(ctx context.Context, rep *repo.Repository) error { isDir1 := strings.HasPrefix(string(oid1), "k") isDir2 := strings.HasPrefix(string(oid2), "k") if isDir1 != isDir2 { - return fmt.Errorf("arguments do diff must both be directories or both non-directories") + return errors.New("arguments do diff must both be directories or both non-directories") } d, err := diff.NewComparer(rep, os.Stdout) @@ -55,7 +55,7 @@ func runDiffCommand(ctx context.Context, rep *repo.Repository) error { ) } - return fmt.Errorf("comparing files not implemented yet") + return errors.New("comparing files not implemented yet") } func defaultDiffCommand() string { diff --git a/cli/command_mount_browse.go b/cli/command_mount_browse.go index 213d4f426..316ccd550 100644 --- a/cli/command_mount_browse.go +++ b/cli/command_mount_browse.go @@ -1,10 +1,10 @@ package cli import ( - "fmt" "os" "os/exec" + "github.com/pkg/errors" "github.com/skratchdot/open-golang/open" ) @@ -50,7 +50,7 @@ func netUSE(mountPoint string, addr string) error { c.Stderr = os.Stderr c.Stdin = os.Stdin if err := c.Run(); err != nil { - return fmt.Errorf("unable to mount: %v", err) + return errors.Wrap(err, "unable to mount") } startWebBrowser("x:\\") @@ -61,7 +61,7 @@ func netUSE(mountPoint string, addr string) error { c.Stderr = os.Stderr c.Stdin = os.Stdin if err := c.Run(); err != nil { - return fmt.Errorf("unable to unmount: %v", err) + return errors.Wrap(err, "unable to unmount") } return nil diff --git a/cli/command_mount_nofuse.go b/cli/command_mount_nofuse.go index 7a161b49c..0b24abaa0 100644 --- a/cli/command_mount_nofuse.go +++ b/cli/command_mount_nofuse.go @@ -3,9 +3,8 @@ package cli import ( - "fmt" - "github.com/kopia/kopia/fs" + "github.com/pkg/errors" ) var ( @@ -13,5 +12,5 @@ ) func mountDirectoryFUSE(entry fs.Directory, mountPoint string) error { - return fmt.Errorf("FUSE is not supported") + return errors.New("FUSE is not supported") } diff --git a/cli/command_policy.go b/cli/command_policy.go index c93e5bf41..d6d7dc705 100644 --- a/cli/command_policy.go +++ b/cli/command_policy.go @@ -2,16 +2,16 @@ import ( "context" - "fmt" "github.com/kopia/kopia/snapshot" "github.com/kopia/kopia/snapshot/policy" "github.com/kopia/repo" + "github.com/pkg/errors" ) func policyTargets(ctx context.Context, rep *repo.Repository, globalFlag *bool, targetsFlag *[]string) ([]snapshot.SourceInfo, error) { if *globalFlag == (len(*targetsFlag) > 0) { - return nil, fmt.Errorf("must pass either '--global' or a list of path targets") + return nil, errors.New("must pass either '--global' or a list of path targets") } if *globalFlag { diff --git a/cli/command_policy_set.go b/cli/command_policy_set.go index c3c1a81be..eb05a4a9c 100644 --- a/cli/command_policy_set.go +++ b/cli/command_policy_set.go @@ -8,9 +8,10 @@ "strings" "github.com/kopia/kopia/fs/ignorefs" - "github.com/kopia/repo" "github.com/kopia/kopia/snapshot" "github.com/kopia/kopia/snapshot/policy" + "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -73,7 +74,7 @@ func setPolicy(ctx context.Context, rep *repo.Repository) error { } if changeCount == 0 { - return fmt.Errorf("no changes specified") + return errors.New("no changes specified") } if err := policy.SetPolicy(ctx, rep, target, p); err != nil { @@ -86,19 +87,19 @@ func setPolicy(ctx context.Context, rep *repo.Repository) error { func setPolicyFromFlags(target snapshot.SourceInfo, p *policy.Policy, changeCount *int) error { if err := setRetentionPolicyFromFlags(&p.RetentionPolicy, changeCount); err != nil { - return fmt.Errorf("retention policy: %v", err) + return errors.Wrap(err, "retention policy") } if err := setFilesPolicyFromFlags(&p.FilesPolicy, changeCount); err != nil { - return fmt.Errorf("files policy: %v", err) + return errors.Wrap(err, "files policy") } if err := setSchedulingPolicyFromFlags(&p.SchedulingPolicy, changeCount); err != nil { - return fmt.Errorf("scheduling policy: %v", err) + return errors.Wrap(err, "scheduling policy") } if err := applyPolicyNumber64("maximum file size", &p.FilesPolicy.MaxFileSize, *policySetMaxFileSize, changeCount); err != nil { - return fmt.Errorf("maximum file size: %v", err) + return errors.Wrap(err, "maximum file size") } // It's not really a list, just optional boolean, last one wins. @@ -171,7 +172,7 @@ func setSchedulingPolicyFromFlags(sp *policy.SchedulingPolicy, changeCount *int) var timeOfDay policy.TimeOfDay if err := timeOfDay.Parse(tod); err != nil { - return fmt.Errorf("unable to parse time of day: %v", err) + return errors.Wrap(err, "unable to parse time of day") } timesOfDay = append(timesOfDay, timeOfDay) } diff --git a/cli/command_repository_connect.go b/cli/command_repository_connect.go index 9bbf7aa38..b442cbce2 100644 --- a/cli/command_repository_connect.go +++ b/cli/command_repository_connect.go @@ -2,12 +2,12 @@ import ( "context" - "fmt" "time" "github.com/kopia/repo" "github.com/kopia/repo/block" "github.com/kopia/repo/storage" + "github.com/pkg/errors" "gopkg.in/alecthomas/kingpin.v2" ) @@ -56,7 +56,7 @@ func runConnectCommandWithStorageAndPassword(ctx context.Context, st storage.Sto if connectPersistCredentials { if err := persistPassword(configFile, getUserName(), password); err != nil { - return fmt.Errorf("unable to persist password: %v", err) + return errors.Wrap(err, "unable to persist password") } } else { deletePassword(configFile, getUserName()) diff --git a/cli/command_repository_connect_from_config.go b/cli/command_repository_connect_from_config.go index e599a15cc..521136f46 100644 --- a/cli/command_repository_connect_from_config.go +++ b/cli/command_repository_connect_from_config.go @@ -2,11 +2,11 @@ import ( "context" - "fmt" "os" "github.com/kopia/repo" "github.com/kopia/repo/storage" + "github.com/pkg/errors" kingpin "gopkg.in/alecthomas/kingpin.v2" ) @@ -17,12 +17,12 @@ func connectToStorageFromConfig(ctx context.Context) (storage.Storage, error) { f, err := os.Open(connectToStorageFromConfigPath) if err != nil { - return nil, fmt.Errorf("unable to open config: %v", err) + return nil, errors.Wrap(err, "unable to open config") } defer f.Close() //nolint:errcheck if err := cfg.Load(f); err != nil { - return nil, fmt.Errorf("unable to load config: %v", err) + return nil, errors.Wrap(err, "unable to load config") } return storage.NewStorage(ctx, cfg.Storage) diff --git a/cli/command_repository_create.go b/cli/command_repository_create.go index 3d0115721..e05b98116 100644 --- a/cli/command_repository_create.go +++ b/cli/command_repository_create.go @@ -2,8 +2,6 @@ import ( "context" - "errors" - "fmt" "strings" "github.com/kopia/kopia/fs/ignorefs" @@ -13,6 +11,7 @@ "github.com/kopia/repo/block" "github.com/kopia/repo/object" "github.com/kopia/repo/storage" + "github.com/pkg/errors" ) var ( @@ -69,7 +68,7 @@ func ensureEmpty(ctx context.Context, s storage.Storage) error { }) if err == hasDataError { if !*createOverwrite { - return fmt.Errorf("found existing data in storage, specify --overwrite to use anyway") + return errors.New("found existing data in storage, specify --overwrite to use anyway") } } @@ -79,7 +78,7 @@ func ensureEmpty(ctx context.Context, s storage.Storage) error { func runCreateCommandWithStorage(ctx context.Context, st storage.Storage) error { err := ensureEmpty(ctx, st) if err != nil { - return fmt.Errorf("unable to get repository storage: %v", err) + return errors.Wrap(err, "unable to get repository storage") } options := newRepositoryOptionsFromFlags() @@ -104,7 +103,7 @@ func runCreateCommandWithStorage(ctx context.Context, st storage.Storage) error } if err := repo.Initialize(ctx, st, options, password); err != nil { - return fmt.Errorf("cannot initialize repository: %v", err) + return errors.Wrap(err, "cannot initialize repository") } if *createOnly { @@ -112,7 +111,7 @@ func runCreateCommandWithStorage(ctx context.Context, st storage.Storage) error } if err := runConnectCommandWithStorageAndPassword(ctx, st, password); err != nil { - return fmt.Errorf("unable to connect to repository: %v", err) + return errors.Wrap(err, "unable to connect to repository") } return populateRepository(ctx, password) @@ -121,17 +120,17 @@ func runCreateCommandWithStorage(ctx context.Context, st storage.Storage) error func populateRepository(ctx context.Context, password string) error { rep, err := repo.Open(ctx, repositoryConfigFileName(), password, applyOptionsFromFlags(nil)) if err != nil { - return fmt.Errorf("unable to open repository: %v", err) + return errors.Wrap(err, "unable to open repository") } defer rep.Close(ctx) //nolint:errcheck globalPolicy, err := getInitialGlobalPolicy() if err != nil { - return fmt.Errorf("unable to initialize global policy: %v", err) + return errors.Wrap(err, "unable to initialize global policy") } if err := policy.SetPolicy(ctx, rep, policy.GlobalPolicySourceInfo, globalPolicy); err != nil { - return fmt.Errorf("unable to set global policy: %v", err) + return errors.Wrap(err, "unable to set global policy") } printPolicy(globalPolicy, nil) @@ -148,7 +147,7 @@ func getInitialGlobalPolicy() (*policy.Policy, error) { for _, tod := range strings.Split(tods, ",") { var timeOfDay policy.TimeOfDay if err := timeOfDay.Parse(tod); err != nil { - return nil, fmt.Errorf("unable to parse time of day: %v", err) + return nil, errors.Wrap(err, "unable to parse time of day") } timesOfDay = append(timesOfDay, timeOfDay) } diff --git a/cli/command_repository_repair.go b/cli/command_repository_repair.go index f16d8f049..491f67ba8 100644 --- a/cli/command_repository_repair.go +++ b/cli/command_repository_repair.go @@ -2,11 +2,10 @@ import ( "context" - "errors" - "fmt" "github.com/kopia/repo" "github.com/kopia/repo/storage" + "github.com/pkg/errors" ) var ( @@ -63,7 +62,7 @@ func recoverFormatBlock(ctx context.Context, st storage.Storage, prefix string) case errSuccess: return nil case nil: - return fmt.Errorf("could not find a replica of a format block") + return errors.New("could not find a replica of a format block") default: return err } diff --git a/cli/command_server_start.go b/cli/command_server_start.go index be100a195..8fddbd8e7 100644 --- a/cli/command_server_start.go +++ b/cli/command_server_start.go @@ -2,12 +2,12 @@ import ( "context" - "fmt" "net/http" "time" "github.com/kopia/kopia/internal/server" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -24,7 +24,7 @@ func init() { func runServer(ctx context.Context, rep *repo.Repository) error { srv, err := server.New(ctx, rep, getHostName(), getUserName()) if err != nil { - return fmt.Errorf("unable to initialize server: %v", err) + return errors.Wrap(err, "unable to initialize server") } go rep.RefreshPeriodically(ctx, 10*time.Second) diff --git a/cli/command_snapshot_create.go b/cli/command_snapshot_create.go index b191196b4..a169c7e49 100644 --- a/cli/command_snapshot_create.go +++ b/cli/command_snapshot_create.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "os" "os/user" @@ -15,6 +14,7 @@ "github.com/kopia/kopia/snapshot/policy" "github.com/kopia/kopia/snapshot/snapshotfs" "github.com/kopia/repo" + "github.com/pkg/errors" ) const ( @@ -57,7 +57,7 @@ func runBackupCommand(ctx context.Context, rep *repo.Repository) error { u.Progress = cliProgress if len(*snapshotCreateDescription) > maxSnapshotDescriptionLength { - return fmt.Errorf("description too long") + return errors.New("description too long") } var finalErrors []string @@ -80,7 +80,7 @@ func runBackupCommand(ctx context.Context, rep *repo.Repository) error { return nil } - return fmt.Errorf("encountered %v errors:\n%v", len(finalErrors), strings.Join(finalErrors, "\n")) + return errors.Errorf("encountered %v errors:\n%v", len(finalErrors), strings.Join(finalErrors, "\n")) } func snapshotSingleSource(ctx context.Context, rep *repo.Repository, u *snapshotfs.Uploader, sourceInfo snapshot.SourceInfo) error { @@ -109,7 +109,7 @@ func snapshotSingleSource(ctx context.Context, rep *repo.Repository, u *snapshot snapID, err := snapshot.SaveSnapshot(ctx, rep, manifest) if err != nil { - return fmt.Errorf("cannot save manifest: %v", err) + return errors.Wrap(err, "cannot save manifest") } printStderr("uploaded snapshot %v (root %v) in %v\n", snapID, manifest.RootObjectID(), time.Since(t0)) @@ -122,7 +122,7 @@ func snapshotSingleSource(ctx context.Context, rep *repo.Repository, u *snapshot func findPreviousSnapshotManifest(ctx context.Context, rep *repo.Repository, sourceInfo snapshot.SourceInfo, noLaterThan *time.Time) (*snapshot.Manifest, error) { previous, err := snapshot.ListSnapshots(ctx, rep, sourceInfo) if err != nil { - return nil, fmt.Errorf("error listing previous backups: %v", err) + return nil, errors.Wrap(err, "error listing previous backups") } var previousManifest *snapshot.Manifest @@ -151,7 +151,7 @@ func getLocalBackupPaths(ctx context.Context, rep *repo.Repository) ([]string, e sources, err := snapshot.ListSources(ctx, rep) if err != nil { - return nil, fmt.Errorf("unable to list sources: %v", err) + return nil, errors.Wrap(err, "unable to list sources") } var result []string diff --git a/cli/command_snapshot_migrate.go b/cli/command_snapshot_migrate.go index c34addd26..536cc1f6f 100644 --- a/cli/command_snapshot_migrate.go +++ b/cli/command_snapshot_migrate.go @@ -10,6 +10,7 @@ "github.com/kopia/kopia/snapshot" "github.com/kopia/kopia/snapshot/snapshotfs" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -25,12 +26,12 @@ func runMigrateCommand(ctx context.Context, destRepo *repo.Repository) error { sourceRepo, err := repo.Open(ctx, *migrateSourceConfig, mustGetPasswordFromFlags(false, false), applyOptionsFromFlags(nil)) if err != nil { - return fmt.Errorf("can't open source repository: %v", err) + return errors.Wrap(err, "can't open source repository") } sources, err := getSourcesToMigrate(ctx, sourceRepo) if err != nil { - return fmt.Errorf("can't retrieve sources: %v", err) + return errors.Wrap(err, "can't retrieve sources") } semaphore := make(chan struct{}, *migrateParallelism) @@ -94,7 +95,7 @@ func runMigrateCommand(ctx context.Context, destRepo *repo.Repository) error { func findPreviousSnapshotManifestWithStartTime(ctx context.Context, rep *repo.Repository, sourceInfo snapshot.SourceInfo, startTime time.Time) (*snapshot.Manifest, error) { previous, err := snapshot.ListSnapshots(ctx, rep, sourceInfo) if err != nil { - return nil, fmt.Errorf("error listing previous backups: %v", err) + return nil, errors.Wrap(err, "error listing previous backups") } for _, p := range previous { @@ -166,7 +167,7 @@ func migrateSingleSourceSnapshot(ctx context.Context, uploader *snapshotfs.Uploa newm.Description = m.Description if newm.IncompleteReason == "" { if _, err := snapshot.SaveSnapshot(ctx, destRepo, newm); err != nil { - return fmt.Errorf("cannot save manifest: %v", err) + return errors.Wrap(err, "cannot save manifest") } } return nil @@ -199,7 +200,7 @@ func getSourcesToMigrate(ctx context.Context, rep *repo.Repository) ([]snapshot. return snapshot.ListSources(ctx, rep) } - return nil, fmt.Errorf("must specify either --all or --sources") + return nil, errors.New("must specify either --all or --sources") } func init() { diff --git a/cli/config.go b/cli/config.go index 8ce8d196b..4bc648746 100644 --- a/cli/config.go +++ b/cli/config.go @@ -13,6 +13,7 @@ "github.com/kopia/kopia/fs/loggingfs" "github.com/kopia/kopia/internal/ospath" "github.com/kopia/repo" + "github.com/pkg/errors" ) var ( @@ -66,7 +67,7 @@ func waitForCtrlC() { func openRepository(ctx context.Context, opts *repo.Options) (*repo.Repository, error) { r, err := repo.Open(ctx, repositoryConfigFileName(), mustGetPasswordFromFlags(false, true), applyOptionsFromFlags(opts)) if os.IsNotExist(err) { - return nil, fmt.Errorf("not connected to a repository, use 'kopia connect'") + return nil, errors.New("not connected to a repository, use 'kopia connect'") } return r, err diff --git a/cli/password.go b/cli/password.go index aeab30e5e..86c5ae840 100644 --- a/cli/password.go +++ b/cli/password.go @@ -11,6 +11,7 @@ "strings" "github.com/bgentry/speakeasy" + "github.com/pkg/errors" keyring "github.com/zalando/go-keyring" ) @@ -72,7 +73,7 @@ func askPass(prompt string) (string, error) { return p, nil } - return "", fmt.Errorf("can't get password") + return "", errors.New("can't get password") } func getPersistedPassword(configFile string, username string) (string, bool) { diff --git a/cli/show_utils.go b/cli/show_utils.go index d707ae072..71bf940a3 100644 --- a/cli/show_utils.go +++ b/cli/show_utils.go @@ -11,6 +11,7 @@ "time" "github.com/kopia/kopia/internal/units" + "github.com/pkg/errors" "gopkg.in/alecthomas/kingpin.v2" ) @@ -34,7 +35,7 @@ func showContentWithFlags(rd io.Reader, unzip, indentJSON bool) error { if unzip { gz, err := gzip.NewReader(rd) if err != nil { - return fmt.Errorf("unable to open gzip stream: %v", err) + return errors.Wrap(err, "unable to open gzip stream") } rd = gz diff --git a/cli/storage_providers.go b/cli/storage_providers.go index d72017d93..6489f7b2d 100644 --- a/cli/storage_providers.go +++ b/cli/storage_providers.go @@ -2,9 +2,9 @@ import ( "context" - "fmt" "github.com/kopia/repo/storage" + "github.com/pkg/errors" kingpin "gopkg.in/alecthomas/kingpin.v2" ) @@ -24,7 +24,7 @@ func RegisterStorageConnectFlags( ctx := context.Background() st, err := connect(ctx) if err != nil { - return fmt.Errorf("can't connect to storage: %v", err) + return errors.Wrap(err, "can't connect to storage") } return runCreateCommandWithStorage(ctx, st) @@ -38,7 +38,7 @@ func RegisterStorageConnectFlags( ctx := context.Background() st, err := connect(ctx) if err != nil { - return fmt.Errorf("can't connect to storage: %v", err) + return errors.Wrap(err, "can't connect to storage") } return runConnectCommandWithStorage(ctx, st) @@ -51,7 +51,7 @@ func RegisterStorageConnectFlags( ctx := context.Background() st, err := connect(ctx) if err != nil { - return fmt.Errorf("can't connect to storage: %v", err) + return errors.Wrap(err, "can't connect to storage") } return runRepairCommandWithStorage(ctx, st) diff --git a/fs/ignorefs/ignorefs.go b/fs/ignorefs/ignorefs.go index 406d11a25..2ba5098f6 100644 --- a/fs/ignorefs/ignorefs.go +++ b/fs/ignorefs/ignorefs.go @@ -9,6 +9,7 @@ "github.com/kopia/kopia/fs" "github.com/kopia/kopia/internal/ignore" + "github.com/pkg/errors" ) // IgnoreCallback is a function called by ignorefs to report whenever a file or directory is being ignored while listing its parent. @@ -208,7 +209,7 @@ func combineAndDedupe(slices ...[]string) []string { func parseIgnoreFile(ctx context.Context, baseDir string, file fs.File) ([]ignore.Matcher, error) { f, err := file.Open(ctx) if err != nil { - return nil, fmt.Errorf("unable to open ignore file: %v", err) + return nil, errors.Wrap(err, "unable to open ignore file") } defer f.Close() //nolint:errcheck diff --git a/go.mod b/go.mod index 8f8afba3a..a227ef56a 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/kopia/repo v0.3.0-pre2 github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 + github.com/pkg/errors v0.8.1 github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c github.com/stretchr/testify v1.3.0 // indirect github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 diff --git a/go.sum b/go.sum index 8af9ea6bc..53d824393 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= diff --git a/internal/diff/diff.go b/internal/diff/diff.go index 8be519034..35267d938 100644 --- a/internal/diff/diff.go +++ b/internal/diff/diff.go @@ -13,6 +13,7 @@ "github.com/kopia/kopia/internal/kopialogging" "github.com/kopia/repo" "github.com/kopia/repo/object" + "github.com/pkg/errors" ) var log = kopialogging.Logger("diff") @@ -171,7 +172,7 @@ func (c *Comparer) compareFiles(ctx context.Context, f1, f2 fs.File, fname strin oldFile := filepath.Join(c.tmpDir, oldName) if err := c.downloadFile(ctx, f1, oldFile); err != nil { - return fmt.Errorf("error downloading old file: %v", err) + return errors.Wrap(err, "error downloading old file") } defer os.Remove(oldFile) //nolint:errcheck @@ -182,7 +183,7 @@ func (c *Comparer) compareFiles(ctx context.Context, f1, f2 fs.File, fname strin newFile := filepath.Join(c.tmpDir, newName) if err := c.downloadFile(ctx, f2, newFile); err != nil { - return fmt.Errorf("error downloading new file: %v", err) + return errors.Wrap(err, "error downloading new file") } defer os.Remove(newFile) //nolint:errcheck } diff --git a/internal/editor/editor.go b/internal/editor/editor.go index e2f0d0624..e8ef5b3ca 100644 --- a/internal/editor/editor.go +++ b/internal/editor/editor.go @@ -3,6 +3,7 @@ import ( "bufio" + "errors" "fmt" "io/ioutil" "os" @@ -52,7 +53,7 @@ func EditLoop(fname string, initial string, parse func(updated string) error) er var shouldReopen string fmt.Scanf("%s", &shouldReopen) //nolint:errcheck if strings.HasPrefix(strings.ToLower(shouldReopen), "n") { - return fmt.Errorf("aborted") + return errors.New("aborted") } } } diff --git a/internal/server/server.go b/internal/server/server.go index f6a0b684f..f29cca499 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -3,7 +3,6 @@ import ( "context" "encoding/json" - "fmt" "net/http" "net/url" "sync" @@ -13,6 +12,7 @@ "github.com/kopia/kopia/internal/serverapi" "github.com/kopia/kopia/snapshot" "github.com/kopia/repo" + "github.com/pkg/errors" ) var log = kopialogging.Logger("kopia/server") @@ -130,7 +130,7 @@ func New(ctx context.Context, rep *repo.Repository, hostname string, username st sources, err := snapshot.ListSources(ctx, rep) if err != nil { - return nil, fmt.Errorf("unable to list sources: %v", err) + return nil, errors.Wrap(err, "unable to list sources") } for _, src := range sources { diff --git a/internal/serverapi/client.go b/internal/serverapi/client.go index d86b4d034..36f074247 100644 --- a/internal/serverapi/client.go +++ b/internal/serverapi/client.go @@ -5,6 +5,8 @@ "encoding/json" "fmt" "net/http" + + "github.com/pkg/errors" ) // Client provides helper methods for communicating with Kopia API serevr. @@ -25,7 +27,7 @@ func (c *Client) Get(path string, respPayload interface{}) error { return fmt.Errorf("invalid server response: %v", resp.Status) } if err := json.NewDecoder(resp.Body).Decode(respPayload); err != nil { - return fmt.Errorf("malformed server response: %v", err) + return errors.Wrap(err, "malformed server response") } return nil @@ -36,7 +38,7 @@ func (c *Client) Post(path string, reqPayload, respPayload interface{}) error { var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(reqPayload); err != nil { - return fmt.Errorf("unable to encode request: %v", err) + return errors.Wrap(err, "unable to encode request") } resp, err := c.client.Post(c.baseURL+path, "application/json", &buf) @@ -49,7 +51,7 @@ func (c *Client) Post(path string, reqPayload, respPayload interface{}) error { return fmt.Errorf("invalid server response: %v", resp.Status) } if err := json.NewDecoder(resp.Body).Decode(respPayload); err != nil { - return fmt.Errorf("malformed server response: %v", err) + return errors.Wrap(err, "malformed server response") } return nil diff --git a/internal/webdavmount/webdavmount.go b/internal/webdavmount/webdavmount.go index 942462d95..783406c43 100644 --- a/internal/webdavmount/webdavmount.go +++ b/internal/webdavmount/webdavmount.go @@ -1,7 +1,6 @@ package webdavmount import ( - "errors" "fmt" "os" "strings" @@ -9,6 +8,7 @@ "github.com/kopia/kopia/fs" "github.com/kopia/kopia/internal/kopialogging" + "github.com/pkg/errors" "golang.org/x/net/context" "golang.org/x/net/webdav" ) @@ -177,7 +177,7 @@ func (w *webdavFS) findEntry(ctx context.Context, path string) (fs.Entry, error) for i, p := range parts { d, ok := e.(fs.Directory) if !ok { - return nil, fmt.Errorf("%q not found in %q (not a directory)", p, strings.Join(parts[0:i], "/")) + return nil, errors.Errorf("%q not found in %q (not a directory)", p, strings.Join(parts[0:i], "/")) } entries, err := d.Readdir(ctx) @@ -187,7 +187,7 @@ func (w *webdavFS) findEntry(ctx context.Context, path string) (fs.Entry, error) e = entries.FindByName(p) if e == nil { - return nil, fmt.Errorf("%q not found in %q (not found)", p, strings.Join(parts[0:i], "/")) + return nil, errors.Errorf("%q not found in %q (not found)", p, strings.Join(parts[0:i], "/")) } } diff --git a/site/cli2md/cli2md.go b/site/cli2md/cli2md.go index e2ebe5b6b..369b48e09 100644 --- a/site/cli2md/cli2md.go +++ b/site/cli2md/cli2md.go @@ -12,6 +12,7 @@ "github.com/kopia/kopia/cli" _ "github.com/kopia/kopia/internal/logfile" + "github.com/pkg/errors" "gopkg.in/alecthomas/kingpin.v2" ) @@ -111,7 +112,7 @@ func emitArgs(w io.Writer, args []*kingpin.ArgModel) { func generateAppFlags(app *kingpin.ApplicationModel) error { f, err := os.Create(filepath.Join(baseDir, "flags.md")) if err != nil { - return fmt.Errorf("unable to create common flags file: %v", err) + return errors.Wrap(err, "unable to create common flags file") } defer f.Close() @@ -133,7 +134,7 @@ func generateCommands(app *kingpin.ApplicationModel, section string, weight int, } f, err := os.Create(filepath.Join(dir, "_index.md")) if err != nil { - return fmt.Errorf("unable to create common flags file: %v", err) + return errors.Wrap(err, "unable to create common flags file") } defer f.Close() diff --git a/snapshot/manager.go b/snapshot/manager.go index 6755b63cf..6a3a4da76 100644 --- a/snapshot/manager.go +++ b/snapshot/manager.go @@ -3,11 +3,11 @@ import ( "context" - "fmt" "github.com/kopia/kopia/internal/kopialogging" "github.com/kopia/repo" "github.com/kopia/repo/manifest" + "github.com/pkg/errors" ) var log = kopialogging.Logger("kopia/snapshot") @@ -18,7 +18,7 @@ func ListSources(ctx context.Context, rep *repo.Repository) ([]SourceInfo, error "type": "snapshot", }) if err != nil { - return nil, fmt.Errorf("unable to find manifest entries: %v", err) + return nil, errors.Wrap(err, "unable to find manifest entries") } uniq := map[SourceInfo]bool{} @@ -51,7 +51,7 @@ func sourceInfoToLabels(si SourceInfo) map[string]string { func ListSnapshots(ctx context.Context, rep *repo.Repository, si SourceInfo) ([]*Manifest, error) { entries, err := rep.Manifests.Find(ctx, sourceInfoToLabels(si)) if err != nil { - return nil, fmt.Errorf("unable to find manifest entries: %v", err) + return nil, errors.Wrap(err, "unable to find manifest entries") } return LoadSnapshots(ctx, rep, entryIDs(entries)) } @@ -60,7 +60,7 @@ func ListSnapshots(ctx context.Context, rep *repo.Repository, si SourceInfo) ([] func loadSnapshot(ctx context.Context, rep *repo.Repository, manifestID string) (*Manifest, error) { sm := &Manifest{} if err := rep.Manifests.Get(ctx, manifestID, sm); err != nil { - return nil, fmt.Errorf("unable to find manifest entries: %v", err) + return nil, errors.Wrap(err, "unable to find manifest entries") } sm.ID = manifestID @@ -70,13 +70,13 @@ func loadSnapshot(ctx context.Context, rep *repo.Repository, manifestID string) // SaveSnapshot persists given snapshot manifest and returns manifest ID. func SaveSnapshot(ctx context.Context, rep *repo.Repository, manifest *Manifest) (string, error) { if manifest.Source.Host == "" { - return "", fmt.Errorf("missing host") + return "", errors.New("missing host") } if manifest.Source.UserName == "" { - return "", fmt.Errorf("missing username") + return "", errors.New("missing username") } if manifest.Source.Path == "" { - return "", fmt.Errorf("missing path") + return "", errors.New("missing path") } id, err := rep.Manifests.Put(ctx, sourceInfoToLabels(manifest.Source), manifest) @@ -133,7 +133,7 @@ func ListSnapshotManifests(ctx context.Context, rep *repo.Repository, src *Sourc entries, err := rep.Manifests.Find(ctx, labels) if err != nil { - return nil, fmt.Errorf("unable to find manifest entries: %v", err) + return nil, errors.Wrap(err, "unable to find manifest entries") } return entryIDs(entries), nil } diff --git a/snapshot/policy/policy_manager.go b/snapshot/policy/policy_manager.go index 20ed7d69d..acdc4131e 100644 --- a/snapshot/policy/policy_manager.go +++ b/snapshot/policy/policy_manager.go @@ -12,6 +12,7 @@ "github.com/kopia/kopia/snapshot" "github.com/kopia/repo" "github.com/kopia/repo/manifest" + "github.com/pkg/errors" ) // GlobalPolicySourceInfo is a source where global policy is attached. @@ -83,7 +84,7 @@ func GetEffectivePolicy(ctx context.Context, rep *repo.Repository, si snapshot.S func GetDefinedPolicy(ctx context.Context, rep *repo.Repository, si snapshot.SourceInfo) (*Policy, error) { md, err := rep.Manifests.Find(ctx, labelsForSource(si)) if err != nil { - return nil, fmt.Errorf("unable to find policy for source: %v", err) + return nil, errors.Wrap(err, "unable to find policy for source") } if len(md) == 0 { @@ -111,7 +112,7 @@ func GetDefinedPolicy(ctx context.Context, rep *repo.Repository, si snapshot.Sou return p, nil } - return nil, fmt.Errorf("ambiguous policy") + return nil, errors.New("ambiguous policy") } // SetPolicy sets the policy on a given source. @@ -127,7 +128,7 @@ func SetPolicy(ctx context.Context, rep *repo.Repository, si snapshot.SourceInfo for _, em := range md { if err := rep.Manifests.Delete(ctx, em.ID); err != nil { - return fmt.Errorf("unable to delete previous policy manifest: %v", err) + return errors.Wrap(err, "unable to delete previous policy manifest") } } @@ -143,7 +144,7 @@ func RemovePolicy(ctx context.Context, rep *repo.Repository, si snapshot.SourceI for _, em := range md { if err := rep.Manifests.Delete(ctx, em.ID); err != nil { - return fmt.Errorf("unable to delete previous manifest: %v", err) + return errors.Wrap(err, "unable to delete previous manifest") } } @@ -168,7 +169,7 @@ func ListPolicies(ctx context.Context, rep *repo.Repository) ([]*Policy, error) "type": "policy", }) if err != nil { - return nil, fmt.Errorf("unable to list manifests: %v", err) + return nil, errors.Wrap(err, "unable to list manifests") } var policies []*Policy @@ -231,7 +232,7 @@ func FilesPolicyGetter(ctx context.Context, rep *repo.Repository, si snapshot.So rel, err := filepath.Rel(si.Path, policyPath) if err != nil { - return nil, fmt.Errorf("unable to determine relative path: %v", err) + return nil, errors.Wrap(err, "unable to determine relative path") } rel = "./" + rel log.Debugf("loading policy for %v (%v)", policyPath, rel) diff --git a/snapshot/policy/scheduling_policy.go b/snapshot/policy/scheduling_policy.go index bdc312939..74e003744 100644 --- a/snapshot/policy/scheduling_policy.go +++ b/snapshot/policy/scheduling_policy.go @@ -4,6 +4,8 @@ "fmt" "sort" "time" + + "github.com/pkg/errors" ) // TimeOfDay represents the time of day (hh:mm) using 24-hour time format. @@ -15,7 +17,7 @@ type TimeOfDay struct { // Parse parses the time of day. func (t *TimeOfDay) Parse(s string) error { if _, err := fmt.Sscanf(s, "%v:%02v", &t.Hour, &t.Minute); err != nil { - return fmt.Errorf("invalid time of day, must be HH:MM") + return errors.New("invalid time of day, must be HH:MM") } if t.Hour < 0 || t.Hour > 23 { return fmt.Errorf("invalid hour %q, must be between 0 and 23", s) diff --git a/snapshot/snapshotfs/repofs.go b/snapshot/snapshotfs/repofs.go index d72d84737..96bff240b 100644 --- a/snapshot/snapshotfs/repofs.go +++ b/snapshot/snapshotfs/repofs.go @@ -12,6 +12,7 @@ "github.com/kopia/kopia/snapshot" "github.com/kopia/repo" "github.com/kopia/repo/object" + "github.com/pkg/errors" ) type repositoryEntry struct { @@ -181,7 +182,7 @@ func DirectoryEntry(rep *repo.Repository, objectID object.ID, dirSummary *fs.Dir func SnapshotRoot(rep *repo.Repository, man *snapshot.Manifest) (fs.Entry, error) { oid := man.RootObjectID() if oid == "" { - return nil, fmt.Errorf("manifest root object ID") + return nil, errors.New("manifest root object ID") } return newRepoEntry(rep, man.RootEntry), nil diff --git a/snapshot/snapshotfs/upload.go b/snapshot/snapshotfs/upload.go index b414c5e62..6ceaaf179 100644 --- a/snapshot/snapshotfs/upload.go +++ b/snapshot/snapshotfs/upload.go @@ -4,7 +4,6 @@ "bytes" "context" "encoding/binary" - "errors" "fmt" "hash/fnv" "io" @@ -22,6 +21,7 @@ "github.com/kopia/kopia/snapshot" "github.com/kopia/repo" "github.com/kopia/repo/object" + "github.com/pkg/errors" ) var log = kopialogging.Logger("kopia/upload") @@ -103,7 +103,7 @@ func (u *Uploader) cancelReason() string { func (u *Uploader) uploadFileInternal(ctx context.Context, f fs.File, relativePath string) entryResult { file, err := f.Open(ctx) if err != nil { - return entryResult{err: fmt.Errorf("unable to open file: %v", err)} + return entryResult{err: errors.Wrap(err, "unable to open file")} } defer file.Close() //nolint:errcheck @@ -136,7 +136,7 @@ func (u *Uploader) uploadFileInternal(ctx context.Context, f fs.File, relativePa func (u *Uploader) uploadSymlinkInternal(ctx context.Context, f fs.Symlink, relativePath string) entryResult { target, err := f.Readlink(ctx) if err != nil { - return entryResult{err: fmt.Errorf("unable to read symlink: %v", err)} + return entryResult{err: errors.Wrap(err, "unable to read symlink")} } writer := u.repo.Objects.NewWriter(ctx, object.WriterOptions{ @@ -340,7 +340,7 @@ func (u *Uploader) processSubdirectories(ctx context.Context, relativePath strin de := newDirEntry(dir, oid) de.DirSummary = &subdirsumm if err := dw.WriteEntry(de); err != nil { - return fmt.Errorf("unable to write dir entry: %v", err) + return errors.Wrap(err, "unable to write dir entry") } return nil @@ -514,7 +514,7 @@ func (u *Uploader) processUploadWorkItems(workItems []*uploadWorkItem, dw *dirWr } if err := dw.WriteEntry(result.de); err != nil { - return fmt.Errorf("unable to write directory entry: %v", err) + return errors.Wrap(err, "unable to write directory entry") } if result.hash != 0 && it.entry.ModTime().Before(u.hashCacheCutoff) { @@ -523,7 +523,7 @@ func (u *Uploader) processUploadWorkItems(workItems []*uploadWorkItem, dw *dirWr Hash: result.hash, ObjectID: result.de.ObjectID, }); err != nil { - return fmt.Errorf("unable to write hash cache entry: %v", err) + return errors.Wrap(err, "unable to write hash cache entry") } } } @@ -578,7 +578,7 @@ func uploadDirInternal( return "", fs.DirectorySummary{}, err } if err := dw.Finalize(&summ); err != nil { - return "", fs.DirectorySummary{}, fmt.Errorf("unable to finalize directory: %v", err) + return "", fs.DirectorySummary{}, errors.Wrap(err, "unable to finalize directory") } oid, err := writer.Result() diff --git a/snapshot/snapshotfs/upload_test.go b/snapshot/snapshotfs/upload_test.go index 265b5a0bb..4f9cf2cda 100644 --- a/snapshot/snapshotfs/upload_test.go +++ b/snapshot/snapshotfs/upload_test.go @@ -2,7 +2,6 @@ import ( "context" - "fmt" "io/ioutil" "os" "path/filepath" @@ -14,6 +13,7 @@ "github.com/kopia/repo" "github.com/kopia/repo/object" "github.com/kopia/repo/storage/filesystem" + "github.com/pkg/errors" ) const masterPassword = "foofoofoofoofoofoofoofoo" @@ -24,7 +24,7 @@ type uploadTestHarness struct { repo *repo.Repository } -var errTest = fmt.Errorf("test error") +var errTest = errors.New("test error") func (th *uploadTestHarness) cleanup() { os.RemoveAll(th.repoDir)