From c9a4a95848ec6d50dda861a2dad6c7329edc3686 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 30 Jun 2024 11:06:49 +0200 Subject: [PATCH] check: suggest using `repair packs` to repair truncated pack files Previously, that help message was only shown for running `check --read-data`. --- cmd/restic/cmd_check.go | 40 ++++++++++++++++++++++--------------- internal/checker/checker.go | 16 +++++---------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 472cc742a..89bb30868 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -279,14 +279,24 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args orphanedPacks := 0 errChan := make(chan error) + salvagePacks := restic.NewIDSet() printer.P("check all packs\n") go chkr.Packs(ctx, errChan) for err := range errChan { - if checker.IsOrphanedPack(err) { - orphanedPacks++ - printer.P("%v\n", err) + var packErr *checker.PackError + if errors.As(err, &packErr) { + if packErr.Orphaned { + orphanedPacks++ + printer.P("%v\n", err) + } else { + if packErr.Truncated { + salvagePacks.Insert(packErr.ID) + } + errorsFound = true + printer.E("%v\n", err) + } } else if err == checker.ErrLegacyLayout { errorsFound = true printer.E("error: repository still uses the S3 legacy layout\nYou must run `restic migrate s3legacy` to correct this.\n") @@ -355,26 +365,14 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args go chkr.ReadPacks(ctx, packs, p, errChan) - var salvagePacks restic.IDs - for err := range errChan { errorsFound = true printer.E("%v\n", err) if err, ok := err.(*repository.ErrPackData); ok { - salvagePacks = append(salvagePacks, err.PackID) + salvagePacks.Insert(err.PackID) } } p.Done() - - if len(salvagePacks) > 0 { - printer.E("\nThe repository contains damaged pack files. These damaged files must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first.\n\n") - var strIDs []string - for _, id := range salvagePacks { - strIDs = append(strIDs, id.String()) - } - printer.E("restic repair packs %v\nrestic repair snapshots --forget\n\n", strings.Join(strIDs, " ")) - printer.E("Damaged pack files can be caused by backend problem, hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting!\n") - } } switch { @@ -418,6 +416,16 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args doReadData(packs) } + if len(salvagePacks) > 0 { + printer.E("\nThe repository contains damaged pack files. These damaged files must be removed to repair the repository. This can be done using the following commands. Please read the troubleshooting guide at https://restic.readthedocs.io/en/stable/077_troubleshooting.html first.\n\n") + var strIDs []string + for id := range salvagePacks { + strIDs = append(strIDs, id.String()) + } + printer.E("restic repair packs %v\nrestic repair snapshots --forget\n\n", strings.Join(strIDs, " ")) + printer.E("Damaged pack files can be caused by backend problems, hardware problems or bugs in restic. Please open an issue at https://github.com/restic/restic/issues/new/choose for further troubleshooting!\n") + } + if ctx.Err() != nil { return ctx.Err() } diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 82348c7ea..031e13807 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -183,22 +183,16 @@ func (c *Checker) LoadIndex(ctx context.Context, p *progress.Counter) (hints []e // PackError describes an error with a specific pack. type PackError struct { - ID restic.ID - Orphaned bool - Err error + ID restic.ID + Orphaned bool + Truncated bool + Err error } func (e *PackError) Error() string { return "pack " + e.ID.String() + ": " + e.Err.Error() } -// IsOrphanedPack returns true if the error describes a pack which is not -// contained in any index. -func IsOrphanedPack(err error) bool { - var e *PackError - return errors.As(err, &e) && e.Orphaned -} - func isS3Legacy(b backend.Backend) bool { be := backend.AsBackend[*s3.Backend](b) return be != nil && be.Layout.Name() == "s3legacy" @@ -250,7 +244,7 @@ func (c *Checker) Packs(ctx context.Context, errChan chan<- error) { select { case <-ctx.Done(): return - case errChan <- &PackError{ID: id, Err: errors.Errorf("unexpected file size: got %d, expected %d", reposize, size)}: + case errChan <- &PackError{ID: id, Truncated: true, Err: errors.Errorf("unexpected file size: got %d, expected %d", reposize, size)}: } } }