diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 3c4c9daa9..5f03c446b 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -226,7 +226,8 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args } Verbosef("load indexes\n") - hints, errs := chkr.LoadIndex(ctx) + bar := newIndexProgress(gopts.Quiet, gopts.JSON) + hints, errs := chkr.LoadIndex(ctx, bar) errorsFound := false suggestIndexRebuild := false diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 85e078a08..a5bb43731 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -113,13 +113,42 @@ func computePackTypes(ctx context.Context, idx restic.MasterIndex) map[restic.ID } // LoadIndex loads all index files. -func (c *Checker) LoadIndex(ctx context.Context) (hints []error, errs []error) { +func (c *Checker) LoadIndex(ctx context.Context, p *progress.Counter) (hints []error, errs []error) { debug.Log("Start") + indexList, err := backend.MemorizeList(ctx, c.repo.Backend(), restic.IndexFile) + if err != nil { + // abort if an error occurs while listing the indexes + return hints, append(errs, err) + } + + if p != nil { + var numIndexFiles uint64 + err := indexList.List(ctx, restic.IndexFile, func(fi restic.FileInfo) error { + _, err := restic.ParseID(fi.Name) + if err != nil { + debug.Log("unable to parse %v as an ID", fi.Name) + return nil + } + + numIndexFiles++ + return nil + }) + if err != nil { + return hints, append(errs, err) + } + p.SetMax(numIndexFiles) + defer p.Done() + } + packToIndex := make(map[restic.ID]restic.IDSet) - err := index.ForAllIndexes(ctx, c.repo.Backend(), c.repo, func(id restic.ID, index *index.Index, oldFormat bool, err error) error { + err = index.ForAllIndexes(ctx, indexList, c.repo, func(id restic.ID, index *index.Index, oldFormat bool, err error) error { debug.Log("process index %v, err %v", id, err) + if p != nil { + p.Add(1) + } + if oldFormat { debug.Log("index %v has old format", id) hints = append(hints, &ErrOldIndexFormat{id}) diff --git a/internal/checker/checker_test.go b/internal/checker/checker_test.go index 6405ecfbd..ee7e2867c 100644 --- a/internal/checker/checker_test.go +++ b/internal/checker/checker_test.go @@ -77,7 +77,7 @@ func TestCheckRepo(t *testing.T) { repo := repository.TestOpenLocal(t, repodir) chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -103,7 +103,7 @@ func TestMissingPack(t *testing.T) { test.OK(t, repo.Backend().Remove(context.TODO(), packHandle)) chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -136,7 +136,7 @@ func TestUnreferencedPack(t *testing.T) { test.OK(t, repo.Backend().Remove(context.TODO(), indexHandle)) chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -178,7 +178,7 @@ func TestUnreferencedBlobs(t *testing.T) { sort.Sort(unusedBlobsBySnapshot) chkr := checker.New(repo, true) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -258,7 +258,7 @@ func TestModifiedIndex(t *testing.T) { } chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) == 0 { t.Fatalf("expected errors not found") } @@ -279,7 +279,7 @@ func TestDuplicatePacksInIndex(t *testing.T) { repo := repository.TestOpenLocal(t, repodir) chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(hints) == 0 { t.Fatalf("did not get expected checker hints for duplicate packs in indexes") } @@ -347,7 +347,7 @@ func TestCheckerModifiedData(t *testing.T) { chkr := checker.New(checkRepo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -408,7 +408,7 @@ func TestCheckerNoDuplicateTreeDecodes(t *testing.T) { } chkr := checker.New(checkRepo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -524,7 +524,7 @@ func TestCheckerBlobTypeConfusion(t *testing.T) { delayRepo.Unblock() }() - hints, errs := chkr.LoadIndex(ctx) + hints, errs := chkr.LoadIndex(ctx, nil) if len(errs) > 0 { t.Fatalf("expected no errors, got %v: %v", len(errs), errs) } @@ -553,7 +553,7 @@ func loadBenchRepository(t *testing.B) (*checker.Checker, restic.Repository, fun repo := repository.TestOpenLocal(t, repodir) chkr := checker.New(repo, false) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) > 0 { defer cleanup() t.Fatalf("expected no errors, got %v: %v", len(errs), errs) diff --git a/internal/checker/testing.go b/internal/checker/testing.go index 0668406d8..fe1679393 100644 --- a/internal/checker/testing.go +++ b/internal/checker/testing.go @@ -11,7 +11,7 @@ import ( func TestCheckRepo(t testing.TB, repo restic.Repository) { chkr := New(repo, true) - hints, errs := chkr.LoadIndex(context.TODO()) + hints, errs := chkr.LoadIndex(context.TODO(), nil) if len(errs) != 0 { t.Fatalf("errors loading index: %v", errs) } diff --git a/internal/index/master_index_test.go b/internal/index/master_index_test.go index 493d11ace..bf8ec3f41 100644 --- a/internal/index/master_index_test.go +++ b/internal/index/master_index_test.go @@ -382,7 +382,7 @@ func testIndexSave(t *testing.T, version uint) { t.Error(err) } - hints, errs := checker.LoadIndex(context.TODO()) + hints, errs := checker.LoadIndex(context.TODO(), nil) for _, h := range hints { t.Logf("hint: %v\n", h) }