From 223aa22cb01a57c87a3962bd1f78f35659b80881 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 10 May 2024 18:19:14 +0200 Subject: [PATCH] replace some uses of restic.Repository with finegrained interfaces --- internal/index/master_index.go | 2 +- internal/repository/prune.go | 2 +- internal/restic/lock.go | 12 ++++++------ internal/restic/lock_test.go | 4 ++-- internal/restic/parallel.go | 2 +- internal/restic/repository.go | 20 +++++++++++++++++++- internal/restic/testing.go | 2 +- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/internal/index/master_index.go b/internal/index/master_index.go index d99a3434d..21ab344d6 100644 --- a/internal/index/master_index.go +++ b/internal/index/master_index.go @@ -270,7 +270,7 @@ func (mi *MasterIndex) MergeFinalIndexes() error { // Save saves all known indexes to index files, leaving out any // packs whose ID is contained in packBlacklist from finalized indexes. // It also removes the old index files and those listed in extraObsolete. -func (mi *MasterIndex) Save(ctx context.Context, repo restic.Repository, excludePacks restic.IDSet, extraObsolete restic.IDs, opts restic.MasterIndexSaveOpts) error { +func (mi *MasterIndex) Save(ctx context.Context, repo restic.SaverRemoverUnpacked, excludePacks restic.IDSet, extraObsolete restic.IDs, opts restic.MasterIndexSaveOpts) error { p := opts.SaveProgress p.SetMax(uint64(len(mi.Packs(excludePacks)))) diff --git a/internal/repository/prune.go b/internal/repository/prune.go index 8ab16ab15..479439e6a 100644 --- a/internal/repository/prune.go +++ b/internal/repository/prune.go @@ -621,7 +621,7 @@ func (plan *PrunePlan) Execute(ctx context.Context, printer progress.Printer) (e // deleteFiles deletes the given fileList of fileType in parallel // if ignoreError=true, it will print a warning if there was an error, else it will abort. -func deleteFiles(ctx context.Context, ignoreError bool, repo restic.Repository, fileList restic.IDSet, fileType restic.FileType, printer progress.Printer) error { +func deleteFiles(ctx context.Context, ignoreError bool, repo restic.RemoverUnpacked, fileList restic.IDSet, fileType restic.FileType, printer progress.Printer) error { bar := printer.NewCounter("files deleted") defer bar.Done() diff --git a/internal/restic/lock.go b/internal/restic/lock.go index 127ac643f..1e393c7ed 100644 --- a/internal/restic/lock.go +++ b/internal/restic/lock.go @@ -35,7 +35,7 @@ type Lock struct { UID uint32 `json:"uid,omitempty"` GID uint32 `json:"gid,omitempty"` - repo Repository + repo Unpacked lockID *ID } @@ -86,14 +86,14 @@ var ErrRemovedLock = errors.New("lock file was removed in the meantime") // NewLock returns a new, non-exclusive lock for the repository. If an // exclusive lock is already held by another process, it returns an error // that satisfies IsAlreadyLocked. -func NewLock(ctx context.Context, repo Repository) (*Lock, error) { +func NewLock(ctx context.Context, repo Unpacked) (*Lock, error) { return newLock(ctx, repo, false) } // NewExclusiveLock returns a new, exclusive lock for the repository. If // another lock (normal and exclusive) is already held by another process, // it returns an error that satisfies IsAlreadyLocked. -func NewExclusiveLock(ctx context.Context, repo Repository) (*Lock, error) { +func NewExclusiveLock(ctx context.Context, repo Unpacked) (*Lock, error) { return newLock(ctx, repo, true) } @@ -105,7 +105,7 @@ func TestSetLockTimeout(t testing.TB, d time.Duration) { waitBeforeLockCheck = d } -func newLock(ctx context.Context, repo Repository, excl bool) (*Lock, error) { +func newLock(ctx context.Context, repo Unpacked, excl bool) (*Lock, error) { lock := &Lock{ Time: time.Now(), PID: os.Getpid(), @@ -389,7 +389,7 @@ func LoadLock(ctx context.Context, repo LoaderUnpacked, id ID) (*Lock, error) { } // RemoveStaleLocks deletes all locks detected as stale from the repository. -func RemoveStaleLocks(ctx context.Context, repo Repository) (uint, error) { +func RemoveStaleLocks(ctx context.Context, repo Unpacked) (uint, error) { var processed uint err := ForAllLocks(ctx, repo, nil, func(id ID, lock *Lock, err error) error { if err != nil { @@ -412,7 +412,7 @@ func RemoveStaleLocks(ctx context.Context, repo Repository) (uint, error) { } // RemoveAllLocks removes all locks forcefully. -func RemoveAllLocks(ctx context.Context, repo Repository) (uint, error) { +func RemoveAllLocks(ctx context.Context, repo Unpacked) (uint, error) { var processed uint32 err := ParallelList(ctx, repo, LockFile, repo.Connections(), func(ctx context.Context, id ID, _ int64) error { err := repo.RemoveUnpacked(ctx, LockFile, id) diff --git a/internal/restic/lock_test.go b/internal/restic/lock_test.go index 012341821..b96b11e35 100644 --- a/internal/restic/lock_test.go +++ b/internal/restic/lock_test.go @@ -130,7 +130,7 @@ func createFakeLock(repo restic.SaverUnpacked, t time.Time, pid int) (restic.ID, return restic.SaveJSONUnpacked(context.TODO(), repo, restic.LockFile, &newLock) } -func removeLock(repo restic.Repository, id restic.ID) error { +func removeLock(repo restic.RemoverUnpacked, id restic.ID) error { return repo.RemoveUnpacked(context.TODO(), restic.LockFile, id) } @@ -190,7 +190,7 @@ func TestLockStale(t *testing.T) { } } -func lockExists(repo restic.Repository, t testing.TB, lockID restic.ID) bool { +func lockExists(repo restic.Lister, t testing.TB, lockID restic.ID) bool { var exists bool rtest.OK(t, repo.List(context.TODO(), restic.LockFile, func(id restic.ID, size int64) error { if id == lockID { diff --git a/internal/restic/parallel.go b/internal/restic/parallel.go index 11460bbbd..0c2215325 100644 --- a/internal/restic/parallel.go +++ b/internal/restic/parallel.go @@ -54,7 +54,7 @@ func ParallelList(ctx context.Context, r Lister, t FileType, parallelism uint, f // ParallelRemove deletes the given fileList of fileType in parallel // if callback returns an error, then it will abort. -func ParallelRemove(ctx context.Context, repo Repository, fileList IDSet, fileType FileType, report func(id ID, err error) error, bar *progress.Counter) error { +func ParallelRemove(ctx context.Context, repo RemoverUnpacked, fileList IDSet, fileType FileType, report func(id ID, err error) error, bar *progress.Counter) error { fileChan := make(chan ID) wg, ctx := errgroup.WithContext(ctx) wg.Go(func() error { diff --git a/internal/restic/repository.go b/internal/restic/repository.go index e386630a3..bc0ec2d43 100644 --- a/internal/restic/repository.go +++ b/internal/restic/repository.go @@ -89,6 +89,18 @@ type SaverUnpacked interface { SaveUnpacked(context.Context, FileType, []byte) (ID, error) } +// RemoverUnpacked allows removing an unpacked blob +type RemoverUnpacked interface { + // Connections returns the maximum number of concurrent backend operations + Connections() uint + RemoveUnpacked(ctx context.Context, t FileType, id ID) error +} + +type SaverRemoverUnpacked interface { + SaverUnpacked + RemoverUnpacked +} + type PackBlobs struct { PackID ID Blobs []Blob @@ -111,7 +123,7 @@ type MasterIndex interface { Each(ctx context.Context, fn func(PackedBlob)) error ListPacks(ctx context.Context, packs IDSet) <-chan PackBlobs - Save(ctx context.Context, repo Repository, excludePacks IDSet, extraObsolete IDs, opts MasterIndexSaveOpts) error + Save(ctx context.Context, repo SaverRemoverUnpacked, excludePacks IDSet, extraObsolete IDs, opts MasterIndexSaveOpts) error } // Lister allows listing files in a backend. @@ -123,3 +135,9 @@ type ListerLoaderUnpacked interface { Lister LoaderUnpacked } + +type Unpacked interface { + ListerLoaderUnpacked + SaverUnpacked + RemoverUnpacked +} diff --git a/internal/restic/testing.go b/internal/restic/testing.go index d2acd3ee9..8f86a7b2c 100644 --- a/internal/restic/testing.go +++ b/internal/restic/testing.go @@ -190,7 +190,7 @@ func ParseDurationOrPanic(s string) Duration { // TestLoadAllSnapshots returns a list of all snapshots in the repo. // If a snapshot ID is in excludeIDs, it will not be included in the result. -func TestLoadAllSnapshots(ctx context.Context, repo Repository, excludeIDs IDSet) (snapshots Snapshots, err error) { +func TestLoadAllSnapshots(ctx context.Context, repo ListerLoaderUnpacked, excludeIDs IDSet) (snapshots Snapshots, err error) { err = ForAllSnapshots(ctx, repo, repo, excludeIDs, func(id ID, sn *Snapshot, err error) error { if err != nil { return err