find: fix fallback to index if pack cannot be listed

`find` would only look up completely missing pack files in the index. A
still existing but broken pack file would result in an error.
This commit is contained in:
Michael Eischer
2026-06-14 15:24:57 +02:00
parent 634e9b2411
commit 9670cd7459
2 changed files with 27 additions and 24 deletions
+6
View File
@@ -0,0 +1,6 @@
Enhancement: `find --pack` can handle corrupted pack files
`restic find --pack <id>` can now also report affected snapshot if a packfile
is corrupted but still present in the repository index.
https://github.com/restic/restic/pull/21883
+21 -24
View File
@@ -445,6 +445,17 @@ func (f *Finder) findIDs(ctx context.Context, sn *data.Snapshot) error {
var errAllPacksFound = errors.New("all packs found")
func (f *Finder) addBlobHandle(h restic.BlobHandle) {
switch h.Type {
case restic.DataBlob:
f.blobIDs[h.ID.String()] = struct{}{}
case restic.TreeBlob:
f.treeIDs[h.ID.String()] = struct{}{}
default:
panic(fmt.Sprintf("unknown type %v in blob list", h.Type.String()))
}
}
// packsToBlobs converts the list of pack IDs to a list of blob IDs that
// belong to those packs.
func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error {
@@ -468,37 +479,30 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error {
return nil
}
delete(packIDs, id.Str())
} else {
// forget found id
delete(packIDs, idStr)
packIDs[idStr] = struct{}{}
}
debug.Log("Found pack %s", idStr)
handles, err := f.repo.ListPackHandles(ctx, id, size)
if err != nil {
return err
// ignore error to allow fallback to index
return nil
}
for _, h := range handles {
switch h.Type {
case restic.DataBlob:
f.blobIDs[h.ID.String()] = struct{}{}
case restic.TreeBlob:
f.treeIDs[h.ID.String()] = struct{}{}
default:
panic(fmt.Sprintf("unknown type %v in blob list", h.Type.String()))
}
f.addBlobHandle(h)
}
// forget successfully processed pack
delete(packIDs, idStr)
// Stop searching when all packs have been found
if len(packIDs) == 0 {
return errAllPacksFound
}
return nil
})
if err != nil && err != errAllPacksFound {
if err != nil && !errors.Is(err, errAllPacksFound) {
return err
}
if err != errAllPacksFound {
if len(packIDs) > 0 {
// try to resolve unknown pack ids from the index
packIDs, err = f.indexPacksToBlobs(ctx, packIDs)
if err != nil {
@@ -516,7 +520,7 @@ func (f *Finder) packsToBlobs(ctx context.Context, packs []string) error {
return errors.Fatalf("unable to find pack(s): %v", list)
}
debug.Log("%d blobs found", len(f.blobIDs))
debug.Log("%d blobs %v trees found", len(f.blobIDs), len(f.treeIDs))
return nil
}
@@ -542,7 +546,7 @@ func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struc
}
}
if matchingID {
f.blobIDs[pb.Handle().ID.String()] = struct{}{}
f.addBlobHandle(pb.Handle())
indexPackIDs[idStr] = struct{}{}
}
})
@@ -554,13 +558,6 @@ func (f *Finder) indexPacksToBlobs(ctx context.Context, packIDs map[string]struc
delete(packIDs, id)
}
if len(indexPackIDs) > 0 {
list := make([]string, 0, len(indexPackIDs))
for h := range indexPackIDs {
list = append(list, h)
}
f.printer.E("some pack files are missing from the repository, getting their blobs from the repository index: %v\n\n", list)
}
return packIDs, nil
}