From 95b44490a04d7628e76f5b2930ce2aa3067e81da Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 16 May 2021 00:10:28 +0200 Subject: [PATCH] find: search blob ids for pack in index if pack is missing If a pack file is missing try to determine the contained pack ids based on the repository index. This helps with assessing the damage to a repository before running `rebuild-index`. --- cmd/restic/cmd_find.go | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/cmd/restic/cmd_find.go b/cmd/restic/cmd_find.go index 7f03fc42b..dba2d2cda 100644 --- a/cmd/restic/cmd_find.go +++ b/cmd/restic/cmd_find.go @@ -447,6 +447,11 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error { } if err != errorAllPacksFound { + // try to resolve unknown pack ids from the index + packIDs = f.indexPacksToBlobs(ctx, packIDs) + } + + if len(packIDs) > 0 { list := make([]string, 0, len(packIDs)) for h := range packIDs { list = append(list, h) @@ -460,6 +465,46 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error { return nil } +func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struct{}) map[string]struct{} { + wctx, cancel := context.WithCancel(ctx) + defer cancel() + + // remember which packs were found in the index + indexPackIDs := make(map[string]struct{}) + for pb := range f.repo.Index().Each(wctx) { + idStr := pb.PackID.String() + // keep entry in packIDs as Each() returns individual index entries + matchingID := false + if _, ok := packIDs[idStr]; ok { + matchingID = true + } else { + if _, ok := packIDs[pb.PackID.Str()]; ok { + // expand id + delete(packIDs, pb.PackID.Str()) + packIDs[idStr] = struct{}{} + matchingID = true + } + } + if matchingID { + f.blobIDs[pb.ID.String()] = struct{}{} + indexPackIDs[idStr] = struct{}{} + } + } + + for id := range indexPackIDs { + delete(packIDs, id) + } + + if len(indexPackIDs) > 0 { + list := make([]string, 0, len(indexPackIDs)) + for h := range indexPackIDs { + list = append(list, h) + } + Warnf("some pack files are missing from the repository, getting their blobs from the repository index: %v\n\n", list) + } + return packIDs +} + func (f *Finder) findObjectPack(ctx context.Context, id string, t restic.BlobType) { idx := f.repo.Index()