From 7d36449ea8774c2ed38483eb737215b16fab066a Mon Sep 17 00:00:00 2001 From: Michael Eischer <9106997+MichaelEischer@users.noreply.github.com> Date: Sun, 14 Jun 2026 15:30:00 +0200 Subject: [PATCH] repository: change LoadBlob, LookupBlob and LookupBlobSize to BlobHandles (#21857) --- cmd/restic/cmd_cat.go | 6 ++-- cmd/restic/cmd_copy.go | 6 ++-- cmd/restic/cmd_diff.go | 2 +- cmd/restic/cmd_find.go | 2 +- cmd/restic/cmd_repair_snapshots.go | 2 +- cmd/restic/cmd_stats.go | 4 +-- internal/archiver/archiver.go | 4 +-- internal/archiver/testing.go | 2 +- internal/checker/checker.go | 4 +-- internal/checker/checker_test.go | 28 +++++++++---------- internal/data/find_test.go | 4 +-- internal/data/testing.go | 6 ++-- internal/data/tree.go | 2 +- internal/data/tree_stream.go | 2 +- internal/dump/common.go | 2 +- internal/fuse/file.go | 4 +-- internal/fuse/fuse_test.go | 4 +-- internal/repository/fuzz_test.go | 2 +- internal/repository/prune_test.go | 4 +-- internal/repository/repack_test.go | 8 +++--- internal/repository/repository.go | 26 ++++++++--------- .../repository/repository_internal_test.go | 4 +-- internal/repository/repository_test.go | 16 +++++------ internal/restic/repository.go | 12 ++++---- internal/restorer/filerestorer.go | 8 +++--- internal/restorer/filerestorer_test.go | 4 +-- internal/restorer/restorer.go | 2 +- 27 files changed, 85 insertions(+), 85 deletions(-) diff --git a/cmd/restic/cmd_cat.go b/cmd/restic/cmd_cat.go index f54a5ce44..71b9c2e71 100644 --- a/cmd/restic/cmd_cat.go +++ b/cmd/restic/cmd_cat.go @@ -177,11 +177,11 @@ func runCat(ctx context.Context, gopts global.Options, args []string, term ui.Te } for _, t := range []restic.BlobType{restic.DataBlob, restic.TreeBlob} { - if _, ok := repo.LookupBlobSize(t, id); !ok { + if _, ok := repo.LookupBlobSize(restic.BlobHandle{Type: t, ID: id}); !ok { continue } - buf, err := repo.LoadBlob(ctx, t, id, nil) + buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: t, ID: id}, nil) if err != nil { return err } @@ -208,7 +208,7 @@ func runCat(ctx context.Context, gopts global.Options, args []string, term ui.Te return err } - buf, err := repo.LoadBlob(ctx, restic.TreeBlob, *sn.Tree, nil) + buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: *sn.Tree}, nil) if err != nil { return err } diff --git a/cmd/restic/cmd_copy.go b/cmd/restic/cmd_copy.go index 8466b4066..039019760 100644 --- a/cmd/restic/cmd_copy.go +++ b/cmd/restic/cmd_copy.go @@ -264,8 +264,8 @@ func copyTree(ctx context.Context, srcRepo *repository.Repository, dstRepo resti enqueue := func(h restic.BlobHandle) { lock.Lock() defer lock.Unlock() - if _, ok := dstRepo.LookupBlobSize(h.Type, h.ID); !ok { - pb := srcRepo.LookupBlob(h.Type, h.ID) + if _, ok := dstRepo.LookupBlobSize(h); !ok { + pb := srcRepo.LookupBlob(h) copyBlobs.Insert(h) for _, p := range pb { packList.Insert(p.PackID()) @@ -317,7 +317,7 @@ func copyStats(srcRepo restic.Repository, copyBlobs restic.AssociatedBlobSet, pa countBlobs := 0 sizeBlobs := uint64(0) for blob := range copyBlobs.Keys() { - for _, pb := range srcRepo.LookupBlob(blob.Type, blob.ID) { + for _, pb := range srcRepo.LookupBlob(blob) { countBlobs++ sizeBlobs += uint64(pb.CiphertextLength()) break diff --git a/cmd/restic/cmd_diff.go b/cmd/restic/cmd_diff.go index 883216bbe..bfecee989 100644 --- a/cmd/restic/cmd_diff.go +++ b/cmd/restic/cmd_diff.go @@ -167,7 +167,7 @@ func updateBlobs(repo restic.Loader, blobs restic.AssociatedBlobSet, stats *Diff stats.TreeBlobs++ } - size, found := repo.LookupBlobSize(h.Type, h.ID) + size, found := repo.LookupBlobSize(h) if !found { printError("unable to find blob size for %v", h) continue diff --git a/cmd/restic/cmd_find.go b/cmd/restic/cmd_find.go index d669fe333..5ee140450 100644 --- a/cmd/restic/cmd_find.go +++ b/cmd/restic/cmd_find.go @@ -571,7 +571,7 @@ func (f *Finder) findObjectPack(id string, t restic.BlobType) { return } - blobs := f.repo.LookupBlob(t, rid) + blobs := f.repo.LookupBlob(restic.BlobHandle{Type: t, ID: rid}) if len(blobs) == 0 { f.printer.S("Object %s with type %s not found in the index", t.String(), rid.Str()) return diff --git a/cmd/restic/cmd_repair_snapshots.go b/cmd/restic/cmd_repair_snapshots.go index b6ffbef8b..ab92116dd 100644 --- a/cmd/restic/cmd_repair_snapshots.go +++ b/cmd/restic/cmd_repair_snapshots.go @@ -115,7 +115,7 @@ func runRepairSnapshots(ctx context.Context, gopts global.Options, opts RepairOp var newSize uint64 // check all contents and remove if not available for _, id := range node.Content { - if size, found := repo.LookupBlobSize(restic.DataBlob, id); !found { + if size, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}); !found { ok = false } else { newContent = append(newContent, id) diff --git a/cmd/restic/cmd_stats.go b/cmd/restic/cmd_stats.go index 4f710b7af..90b9259b7 100644 --- a/cmd/restic/cmd_stats.go +++ b/cmd/restic/cmd_stats.go @@ -155,7 +155,7 @@ func runStats(ctx context.Context, opts StatsOptions, gopts global.Options, args if opts.countMode == countModeRawData { // the blob handles have been collected, but not yet counted for blobHandle := range stats.blobs.Keys() { - pbs := repo.LookupBlob(blobHandle.Type, blobHandle.ID) + pbs := repo.LookupBlob(blobHandle) if len(pbs) == 0 { return fmt.Errorf("blob %v not found", blobHandle) } @@ -274,7 +274,7 @@ func statsWalkTree(repo restic.Loader, opts StatsOptions, stats *statsContainer, } if _, ok := stats.fileBlobs[nodePath][blobID]; !ok { // is always a data blob since we're accessing it via a file's Content array - blobSize, found := repo.LookupBlobSize(restic.DataBlob, blobID) + blobSize, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID}) if !found { return fmt.Errorf("blob %s not found for tree %s", blobID, parentTreeID) } diff --git a/internal/archiver/archiver.go b/internal/archiver/archiver.go index 4693b6b03..037abf189 100644 --- a/internal/archiver/archiver.go +++ b/internal/archiver/archiver.go @@ -297,7 +297,7 @@ func (arch *Archiver) loadSubtree(ctx context.Context, node *data.Node) (data.Tr } func (arch *Archiver) wrapLoadTreeError(id restic.ID, err error) error { - if _, ok := arch.Repo.LookupBlobSize(restic.TreeBlob, id); ok { + if _, ok := arch.Repo.LookupBlobSize(restic.BlobHandle{Type: restic.TreeBlob, ID: id}); ok { err = errors.Errorf("tree %v could not be loaded; the repository could be damaged: %v", id, err) } else { err = errors.Errorf("tree %v is not known; the repository could be damaged, run `repair index` to try to repair it", id) @@ -435,7 +435,7 @@ func (fn *futureNode) take(ctx context.Context) futureNodeResult { func (arch *Archiver) allBlobsPresent(previous *data.Node) bool { // check if all blobs are contained in index for _, id := range previous.Content { - if _, ok := arch.Repo.LookupBlobSize(restic.DataBlob, id); !ok { + if _, ok := arch.Repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}); !ok { return false } } diff --git a/internal/archiver/testing.go b/internal/archiver/testing.go index 3a3bafce1..bec70959f 100644 --- a/internal/archiver/testing.go +++ b/internal/archiver/testing.go @@ -243,7 +243,7 @@ func TestEnsureFileContent(ctx context.Context, t testing.TB, repo restic.BlobLo content := make([]byte, len(file.Content)) pos := 0 for _, id := range node.Content { - part, err := repo.LoadBlob(ctx, restic.DataBlob, id, content[pos:]) + part, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: id}, content[pos:]) if err != nil { t.Fatalf("error loading blob %v: %v", id.Str(), err) return diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 1130cd43c..a54ce3825 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -217,7 +217,7 @@ func (c *Checker) checkTree(id restic.ID, tree data.TreeNodeIterator) (errs []er // unfortunately fails in some cases that are not resolvable // by users, so we omit this check, see #1887 - _, found := c.repo.LookupBlobSize(restic.DataBlob, blobID) + _, found := c.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID}) if !found { debug.Log("tree %v references blob %v which isn't contained in index", id, blobID) errs = append(errs, &Error{TreeID: id, Err: errors.Errorf("file %q blob %v not found in index", node.Name, blobID)}) @@ -306,7 +306,7 @@ func (c *Checker) ReadPacks(ctx context.Context, filter func(packs map[restic.ID // convert used blobs into their encompassing packfiles for bh := range c.blobRefs.M.Keys() { - for _, pb := range c.repo.LookupBlob(bh.Type, bh.ID) { + for _, pb := range c.repo.LookupBlob(bh) { filteredPacks[pb.PackID()] = allPacks[pb.PackID()] } } diff --git a/internal/checker/checker_test.go b/internal/checker/checker_test.go index 454063876..1bf7d392e 100644 --- a/internal/checker/checker_test.go +++ b/internal/checker/checker_test.go @@ -397,20 +397,20 @@ type loadTreesOnceRepository struct { DuplicateTree bool } -func (r *loadTreesOnceRepository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) { - if t != restic.TreeBlob { - return r.Repository.LoadBlob(ctx, t, id, buf) +func (r *loadTreesOnceRepository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) { + if bh.Type != restic.TreeBlob { + return r.Repository.LoadBlob(ctx, bh, buf) } r.mutex.Lock() defer r.mutex.Unlock() - if r.loadedTrees.Has(id) { + if r.loadedTrees.Has(bh.ID) { // additionally store error to ensure that it cannot be swallowed r.DuplicateTree = true - return nil, errors.Errorf("trying to load tree with id %v twice", id) + return nil, errors.Errorf("trying to load tree with id %v twice", bh.ID) } - r.loadedTrees.Insert(id) - return r.Repository.LoadBlob(ctx, t, id, buf) + r.loadedTrees.Insert(bh.ID) + return r.Repository.LoadBlob(ctx, bh, buf) } func TestCheckerNoDuplicateTreeDecodes(t *testing.T) { @@ -442,18 +442,18 @@ type delayRepository struct { Triggered bool } -func (r *delayRepository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) { - if t == restic.TreeBlob && id == r.DelayTree { +func (r *delayRepository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) { + if bh.Type == restic.TreeBlob && bh.ID == r.DelayTree { <-r.UnblockChannel } - return r.Repository.LoadBlob(ctx, t, id, buf) + return r.Repository.LoadBlob(ctx, bh, buf) } -func (r *delayRepository) LookupBlobSize(t restic.BlobType, id restic.ID) (uint, bool) { - if id == r.DelayTree && t == restic.DataBlob { +func (r *delayRepository) LookupBlobSize(bh restic.BlobHandle) (uint, bool) { + if bh.ID == r.DelayTree && bh.Type == restic.DataBlob { r.Unblock() } - return r.Repository.LookupBlobSize(t, id) + return r.Repository.LookupBlobSize(bh) } func (r *delayRepository) Unblock() { @@ -484,7 +484,7 @@ func TestCheckerBlobTypeConfusion(t *testing.T) { return nil })) - buf, err := repo.LoadBlob(ctx, restic.TreeBlob, id, nil) + buf, err := repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: id}, nil) test.OK(t, err) test.OK(t, repo.WithBlobUploader(ctx, func(ctx context.Context, uploader restic.BlobSaverWithAsync) error { diff --git a/internal/data/find_test.go b/internal/data/find_test.go index cd74bd00d..284566027 100644 --- a/internal/data/find_test.go +++ b/internal/data/find_test.go @@ -163,11 +163,11 @@ func TestMultiFindUsedBlobs(t *testing.T) { type ForbiddenRepo struct{} -func (r ForbiddenRepo) LoadBlob(context.Context, restic.BlobType, restic.ID, []byte) ([]byte, error) { +func (r ForbiddenRepo) LoadBlob(context.Context, restic.BlobHandle, []byte) ([]byte, error) { return nil, errors.New("should not be called") } -func (r ForbiddenRepo) LookupBlobSize(_ restic.BlobType, _ restic.ID) (uint, bool) { +func (r ForbiddenRepo) LookupBlobSize(_ restic.BlobHandle) (uint, bool) { return 0, false } diff --git a/internal/data/testing.go b/internal/data/testing.go index 19f7fa7b3..79b0ade5d 100644 --- a/internal/data/testing.go +++ b/internal/data/testing.go @@ -202,11 +202,11 @@ func TestLoadAllSnapshots(ctx context.Context, repo restic.ListerLoaderUnpacked, // TestTreeMap returns the trees from the map on LoadTree. type TestTreeMap map[restic.ID][]byte -func (t TestTreeMap) LoadBlob(_ context.Context, tpe restic.BlobType, id restic.ID, _ []byte) ([]byte, error) { - if tpe != restic.TreeBlob { +func (t TestTreeMap) LoadBlob(_ context.Context, bh restic.BlobHandle, _ []byte) ([]byte, error) { + if bh.Type != restic.TreeBlob { return nil, fmt.Errorf("can only load trees") } - tree, ok := t[id] + tree, ok := t[bh.ID] if !ok { return nil, fmt.Errorf("tree not found") } diff --git a/internal/data/tree.go b/internal/data/tree.go index e137dfef2..ed9b727ce 100644 --- a/internal/data/tree.go +++ b/internal/data/tree.go @@ -143,7 +143,7 @@ func (t *treeIterator) assertToken(token json.Token) error { } func LoadTree(ctx context.Context, loader restic.BlobLoader, content restic.ID) (TreeNodeIterator, error) { - rd, err := loader.LoadBlob(ctx, restic.TreeBlob, content, nil) + rd, err := loader.LoadBlob(ctx, restic.BlobHandle{Type: restic.TreeBlob, ID: content}, nil) if err != nil { return nil, err } diff --git a/internal/data/tree_stream.go b/internal/data/tree_stream.go index dc79ae7f0..baf7af2be 100644 --- a/internal/data/tree_stream.go +++ b/internal/data/tree_stream.go @@ -124,7 +124,7 @@ func filterTrees(ctx context.Context, repo restic.Loader, trees restic.IDs, load continue } - treeSize, found := repo.LookupBlobSize(restic.TreeBlob, nextTreeID.ID) + treeSize, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.TreeBlob, ID: nextTreeID.ID}) if found && treeSize > 50*1024*1024 { loadCh = hugeTreeLoaderChan } else { diff --git a/internal/dump/common.go b/internal/dump/common.go index 2c0edf67a..7a609f2a9 100644 --- a/internal/dump/common.go +++ b/internal/dump/common.go @@ -142,7 +142,7 @@ loop: wg.Go(func() error { blob, err := d.cache.GetOrCompute(id, func() ([]byte, error) { - return d.repo.LoadBlob(ctx, restic.DataBlob, id, nil) + return d.repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil) }) if err == nil { diff --git a/internal/fuse/file.go b/internal/fuse/file.go index 6fd042f81..7d7ac330b 100644 --- a/internal/fuse/file.go +++ b/internal/fuse/file.go @@ -82,7 +82,7 @@ func (f *file) Open(ctx context.Context, _ *fuse.OpenRequest, _ *fuse.OpenRespon return nil, ctx.Err() } - size, found := f.root.repo.LookupBlobSize(restic.DataBlob, id) + size, found := f.root.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}) if !found { return nil, errors.Errorf("id %v not found in repository", id) } @@ -107,7 +107,7 @@ func (f *file) Open(ctx context.Context, _ *fuse.OpenRequest, _ *fuse.OpenRespon func (f *openFile) getBlobAt(ctx context.Context, i int) (blob []byte, err error) { blob, err = f.root.blobCache.GetOrCompute(f.node.Content[i], func() ([]byte, error) { - return f.root.repo.LoadBlob(ctx, restic.DataBlob, f.node.Content[i], nil) + return f.root.repo.LoadBlob(ctx, restic.BlobHandle{Type: restic.DataBlob, ID: f.node.Content[i]}, nil) }) if err != nil { debug.Log("LoadBlob(%v, %v) failed: %v", f.node.Name, f.node.Content[i], err) diff --git a/internal/fuse/fuse_test.go b/internal/fuse/fuse_test.go index 05dc5f91e..e1e8caf9d 100644 --- a/internal/fuse/fuse_test.go +++ b/internal/fuse/fuse_test.go @@ -91,11 +91,11 @@ func TestFuseFile(t *testing.T) { memfile []byte ) for _, id := range content { - size, found := repo.LookupBlobSize(restic.DataBlob, id) + size, found := repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: id}) rtest.Assert(t, found, "Expected to find blob id %v", id) filesize += uint64(size) - buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) + buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil) rtest.OK(t, err) if len(buf) != int(size) { diff --git a/internal/repository/fuzz_test.go b/internal/repository/fuzz_test.go index 62dbd167e..8ec381f70 100644 --- a/internal/repository/fuzz_test.go +++ b/internal/repository/fuzz_test.go @@ -25,7 +25,7 @@ func FuzzSaveLoadBlob(f *testing.F) { return err })) - buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, make([]byte, buflen)) + buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, make([]byte, buflen)) if err != nil { t.Fatal(err) } diff --git a/internal/repository/prune_test.go b/internal/repository/prune_test.go index 6bcd99fa5..261c7deed 100644 --- a/internal/repository/prune_test.go +++ b/internal/repository/prune_test.go @@ -28,7 +28,7 @@ func testPrune(t *testing.T, opts repository.PruneOptions, errOnUnused bool) { rtest.OK(t, repo.WithBlobUploader(context.TODO(), func(ctx context.Context, uploader restic.BlobSaverWithAsync) error { // duplicate a few blobs to exercise those code paths for blob := range keep { - buf, err := repo.LoadBlob(ctx, blob.Type, blob.ID, nil) + buf, err := repo.LoadBlob(ctx, blob, nil) rtest.OK(t, err) _, _, _, err = uploader.SaveBlob(ctx, blob.Type, buf, blob.ID, true) rtest.OK(t, err) @@ -180,7 +180,7 @@ func TestPruneSmall(t *testing.T) { // load all blobs for blob := range keep { - _, err := repo.LoadBlob(context.TODO(), blob.Type, blob.ID, nil) + _, err := repo.LoadBlob(context.TODO(), blob, nil) rtest.OK(t, err) } diff --git a/internal/repository/repack_test.go b/internal/repository/repack_test.go index e744a2a14..f20605c4a 100644 --- a/internal/repository/repack_test.go +++ b/internal/repository/repack_test.go @@ -135,7 +135,7 @@ func findPacksForBlobs(t *testing.T, repo restic.Repository, blobs restic.BlobSe packs := restic.NewIDSet() for h := range blobs { - list := repo.LookupBlob(h.Type, h.ID) + list := repo.LookupBlob(h) if len(list) == 0 { t.Fatal("Failed to find blob", h.ID.Str(), "with type", h.Type) } @@ -208,7 +208,7 @@ func testRepack(t *testing.T, version uint) { } for h := range keepBlobs { - list := repo.LookupBlob(h.Type, h.ID) + list := repo.LookupBlob(h) if len(list) == 0 { t.Errorf("unable to find blob %v in repo", h.ID.Str()) continue @@ -227,7 +227,7 @@ func testRepack(t *testing.T, version uint) { } for h := range removeBlobs { - if _, found := repo.LookupBlobSize(h.Type, h.ID); found { + if _, found := repo.LookupBlobSize(h); found { t.Errorf("blob %v still contained in the repo", h) } } @@ -277,7 +277,7 @@ func testRepackCopy(t *testing.T, version uint) { rebuildAndReloadIndex(t, dstRepo) for h := range keepBlobs { - list := dstRepo.LookupBlob(h.Type, h.ID) + list := dstRepo.LookupBlob(h) if len(list) == 0 { t.Errorf("unable to find blob %v in repo", h.ID.Str()) continue diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 0f105743f..d8cb82d9d 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -236,16 +236,16 @@ func sortCachedPacksFirst(cache haver, blobs []*pack.PackedBlob) { copy(blobs[len(cached):], noncached) } -// LoadBlob loads a blob of type t from the repository. +// LoadBlob loads a blob from the repository. // It may use all of buf[:cap(buf)] as scratch space. -func (r *Repository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) { - debug.Log("load %v with id %v (buf len %v, cap %d)", t, id, len(buf), cap(buf)) +func (r *Repository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) { + debug.Log("load %v (buf len %v, cap %d)", bh, len(buf), cap(buf)) // lookup packs - blobs := r.idx.Lookup(restic.BlobHandle{ID: id, Type: t}) + blobs := r.idx.Lookup(bh) if len(blobs) == 0 { - debug.Log("id %v not found in index", id) - return nil, errors.Errorf("id %v not found in repository", id) + debug.Log("id %v not found in index", bh.ID) + return nil, errors.Errorf("id %v not found in repository", bh.ID) } // try cached pack files first @@ -671,8 +671,8 @@ func (r *Repository) Connections() uint { return r.be.Properties().Connections } -func (r *Repository) LookupBlob(tpe restic.BlobType, id restic.ID) []restic.PackBlob { - entries := r.idx.Lookup(restic.BlobHandle{Type: tpe, ID: id}) +func (r *Repository) LookupBlob(bh restic.BlobHandle) []restic.PackBlob { + entries := r.idx.Lookup(bh) out := make([]restic.PackBlob, len(entries)) for i, e := range entries { out[i] = e @@ -681,8 +681,8 @@ func (r *Repository) LookupBlob(tpe restic.BlobType, id restic.ID) []restic.Pack } // LookupBlobSize returns the size of blob id. Also returns pending blobs. -func (r *Repository) LookupBlobSize(tpe restic.BlobType, id restic.ID) (uint, bool) { - return r.idx.LookupSize(restic.BlobHandle{Type: tpe, ID: id}) +func (r *Repository) LookupBlobSize(bh restic.BlobHandle) (uint, bool) { + return r.idx.LookupSize(bh) } // ListBlobs runs fn on all blobs known to the index. When the context is cancelled, @@ -1059,7 +1059,7 @@ func (r *Repository) saveBlobAsync(ctx context.Context, t restic.BlobType, buf [ } type backendLoadFn func(ctx context.Context, h backend.Handle, length int, offset int64, fn func(rd io.Reader) error) error -type loadBlobFn func(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) +type loadBlobFn func(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) // Skip sections with more than 1MB unused blobs const maxUnusedRange = 1 * 1024 * 1024 @@ -1164,7 +1164,7 @@ func streamPackPart(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBl if loadBlobFn != nil { // check whether we can get the remaining blobs somewhere else for _, entry := range blobs { - buf, ierr := loadBlobFn(ctx, entry.Type, entry.ID, nil) + buf, ierr := loadBlobFn(ctx, entry.BlobHandle, nil) err = handleBlobFn(entry.BlobHandle, buf, ierr) if err != nil { break @@ -1191,7 +1191,7 @@ func streamPackPart(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBl if val.Err != nil && loadBlobFn != nil { var ierr error // check whether we can get a valid copy somewhere else - buf, ierr := loadBlobFn(ctx, val.Handle.Type, val.Handle.ID, nil) + buf, ierr := loadBlobFn(ctx, val.Handle, nil) if ierr == nil { // success val.Plaintext = buf diff --git a/internal/repository/repository_internal_test.go b/internal/repository/repository_internal_test.go index 59873bdad..635d98276 100644 --- a/internal/repository/repository_internal_test.go +++ b/internal/repository/repository_internal_test.go @@ -548,8 +548,8 @@ func TestStreamPackFallback(t *testing.T) { } } - loadBlob := func(ctx context.Context, t restic.BlobType, id restic.ID, buf []byte) ([]byte, error) { - if id == blobID { + loadBlob := func(ctx context.Context, bh restic.BlobHandle, buf []byte) ([]byte, error) { + if bh.ID == blobID { return plaintext, nil } return nil, errors.New("unknown blob") diff --git a/internal/repository/repository_test.go b/internal/repository/repository_test.go index 63623b660..cc5719e9c 100644 --- a/internal/repository/repository_test.go +++ b/internal/repository/repository_test.go @@ -66,7 +66,7 @@ func testSave(t *testing.T, version uint, calculateID bool) { })) // read back - buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) + buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil) rtest.OK(t, err) rtest.Equals(t, size, len(buf)) @@ -97,7 +97,7 @@ func testSaveLoadZeroSizedBlob(t *testing.T, version uint) { return nil })) - buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) + buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil) rtest.OK(t, err) rtest.Equals(t, 0, len(buf)) } @@ -138,7 +138,7 @@ func testSavePackMerging(t *testing.T, targetPercentage int, expectedPacks int) // check that all blobs are readable for _, id := range ids { - _, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, nil) + _, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, nil) rtest.OK(t, err) } @@ -201,7 +201,7 @@ func testLoadBlob(t *testing.T, version uint) { base := crypto.CiphertextLength(length) for _, testlength := range []int{0, base - 20, base - 1, base, base + 7, base + 15, base + 1000} { buf = make([]byte, 0, testlength) - buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf) + buf, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, buf) if err != nil { t.Errorf("LoadBlob() returned an error for buffer size %v: %v", testlength, err) continue @@ -230,10 +230,10 @@ func TestLoadBlobBroken(t *testing.T) { c := cache.TestNewCache(t) repo.UseCache(c, t.Logf) - data, err := repo.LoadBlob(context.TODO(), restic.TreeBlob, id, nil) + data, err := repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.TreeBlob, ID: id}, nil) rtest.OK(t, err) rtest.Assert(t, bytes.Equal(buf, data), "data mismatch") - pack := repo.LookupBlob(restic.TreeBlob, id)[0].PackID() + pack := repo.LookupBlob(restic.BlobHandle{Type: restic.TreeBlob, ID: id})[0].PackID() rtest.Assert(t, c.Has(backend.Handle{Type: restic.PackFile, Name: pack.String()}), "expected tree pack to be cached") } @@ -260,7 +260,7 @@ func benchmarkLoadBlob(b *testing.B, version uint) { for i := 0; i < b.N; i++ { var err error - buf, err = repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf) + buf, err = repo.LoadBlob(context.TODO(), restic.BlobHandle{Type: restic.DataBlob, ID: id}, buf) // Checking the SHA-256 with restic.Hash can make up 38% of the time // spent in this loop, so pause the timer. @@ -466,7 +466,7 @@ func TestListPack(t *testing.T) { repo.UseCache(c, t.Logf) // Forcibly cache pack file - packID := repo.LookupBlob(restic.TreeBlob, id)[0].PackID() + packID := repo.LookupBlob(restic.BlobHandle{Type: restic.TreeBlob, ID: id})[0].PackID() rtest.OK(t, be.Load(context.TODO(), backend.Handle{Type: restic.PackFile, IsMetadata: true, Name: packID.String()}, 0, 0, func(rd io.Reader) error { return nil })) // Get size to list pack diff --git a/internal/restic/repository.go b/internal/restic/repository.go index b8dacd8c3..581375848 100644 --- a/internal/restic/repository.go +++ b/internal/restic/repository.go @@ -21,8 +21,8 @@ type Repository interface { LoadIndex(ctx context.Context, p TerminalCounterFactory) error - LookupBlob(t BlobType, id ID) []PackBlob - LookupBlobSize(t BlobType, id ID) (size uint, exists bool) + LookupBlob(bh BlobHandle) []PackBlob + LookupBlobSize(bh BlobHandle) (size uint, exists bool) NewAssociatedBlobSet() AssociatedBlobSet // ListBlobs runs fn on all blobs known to the index. When the context is cancelled, @@ -31,7 +31,7 @@ type Repository interface { // ListPackHandles returns the blob handles stored in the pack file header. ListPackHandles(ctx context.Context, id ID, packSize int64) ([]BlobHandle, error) - LoadBlob(ctx context.Context, t BlobType, id ID, buf []byte) ([]byte, error) + LoadBlob(ctx context.Context, bh BlobHandle, buf []byte) ([]byte, error) LoadBlobsFromPack(ctx context.Context, packID ID, blobs []BlobHandle, handleBlobFn func(blob BlobHandle, buf []byte, err error) error) error // WithUploader starts the necessary workers to upload new blobs. Once the callback returns, @@ -148,7 +148,7 @@ type ListBlobser interface { } type BlobLoader interface { - LoadBlob(context.Context, BlobType, ID, []byte) ([]byte, error) + LoadBlob(context.Context, BlobHandle, []byte) ([]byte, error) } type WithBlobUploader interface { @@ -173,8 +173,8 @@ type BlobSaverAsync interface { // Loader loads a blob from a repository. type Loader interface { - LoadBlob(context.Context, BlobType, ID, []byte) ([]byte, error) - LookupBlobSize(tpe BlobType, id ID) (uint, bool) + LoadBlob(context.Context, BlobHandle, []byte) ([]byte, error) + LookupBlobSize(bh BlobHandle) (uint, bool) Connections() uint } diff --git a/internal/restorer/filerestorer.go b/internal/restorer/filerestorer.go index 3ec312a2c..7bb849ad5 100644 --- a/internal/restorer/filerestorer.go +++ b/internal/restorer/filerestorer.go @@ -47,7 +47,7 @@ type startWarmupFn func(context.Context, restic.IDSet) (restic.WarmupJob, error) // fileRestorer restores set of files type fileRestorer struct { - idx func(restic.BlobType, restic.ID) []restic.PackBlob + idx func(restic.BlobHandle) []restic.PackBlob blobsLoader blobsLoaderFn startWarmup startWarmupFn @@ -68,7 +68,7 @@ type fileRestorer struct { func newFileRestorer(dst string, blobsLoader blobsLoaderFn, - idx func(restic.BlobType, restic.ID) []restic.PackBlob, + idx func(restic.BlobHandle) []restic.PackBlob, connections uint, sparse bool, allowRecursiveDelete bool, @@ -109,7 +109,7 @@ func (r *fileRestorer) forEachBlob(blobIDs []restic.ID, fn func(blob restic.Pack fileOffset := int64(0) for i, blobID := range blobIDs { - packs := r.idx(restic.DataBlob, blobID) + packs := r.idx(restic.BlobHandle{Type: restic.DataBlob, ID: blobID}) if len(packs) == 0 { return errors.Errorf("Unknown blob %s", blobID.String()) } @@ -290,7 +290,7 @@ func (r *fileRestorer) downloadPack(ctx context.Context, pack *packInfo) error { } } else if packsMap, ok := file.blobs.(map[restic.ID][]fileBlobInfo); ok { for _, blob := range packsMap[pack.id] { - idxPacks := r.idx(restic.DataBlob, blob.id) + idxPacks := r.idx(restic.BlobHandle{Type: restic.DataBlob, ID: blob.id}) for _, idxPack := range idxPacks { if idxPack.PackID().Equal(pack.id) { addBlob(idxPack.Handle(), blob.offset) diff --git a/internal/restorer/filerestorer_test.go b/internal/restorer/filerestorer_test.go index 389604726..adb4e9cd1 100644 --- a/internal/restorer/filerestorer_test.go +++ b/internal/restorer/filerestorer_test.go @@ -67,8 +67,8 @@ type TestRepo struct { loader blobsLoaderFn } -func (i *TestRepo) Lookup(_ restic.BlobType, id restic.ID) []restic.PackBlob { - packs := i.blobs[id] +func (i *TestRepo) Lookup(bh restic.BlobHandle) []restic.PackBlob { + packs := i.blobs[bh.ID] return packs } diff --git a/internal/restorer/restorer.go b/internal/restorer/restorer.go index 7ec9518dc..8741522e4 100644 --- a/internal/restorer/restorer.go +++ b/internal/restorer/restorer.go @@ -744,7 +744,7 @@ func (res *Restorer) verifyFile(ctx context.Context, target string, node *data.N if ctx.Err() != nil { return nil, buf, ctx.Err() } - length, found := res.repo.LookupBlobSize(restic.DataBlob, blobID) + length, found := res.repo.LookupBlobSize(restic.BlobHandle{Type: restic.DataBlob, ID: blobID}) if !found { return nil, buf, errors.Errorf("Unable to fetch blob %s", blobID) }