diff --git a/cmd/restic/lock.go b/cmd/restic/lock.go index a1b6ad5cb..38fc79a0c 100644 --- a/cmd/restic/lock.go +++ b/cmd/restic/lock.go @@ -16,7 +16,7 @@ func internalOpenWithLocked(ctx context.Context, gopts global.Options, dryRun bo unlock := func() {} if !dryRun { - var lock *repository.Unlocker + var lock repository.Unlocker lock, ctx, err = repository.Lock(ctx, repo, exclusive, gopts.RetryLock, func(msg string) { if !gopts.JSON { diff --git a/internal/repository/lock.go b/internal/repository/lock.go index a50195233..d794f03e7 100644 --- a/internal/repository/lock.go +++ b/internal/repository/lock.go @@ -37,13 +37,13 @@ var lockerInst = &locker{ refreshabilityTimeout: restic.StaleLockTimeout - defaultRefreshInterval*3/2, } -func Lock(ctx context.Context, repo *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{})) (*Unlocker, context.Context, error) { +func Lock(ctx context.Context, repo *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{})) (Unlocker, context.Context, error) { return lockerInst.Lock(ctx, repo, exclusive, retryLock, printRetry, logger) } // Lock wraps the ctx such that it is cancelled when the repository is unlocked // cancelling the original context also stops the lock refresh -func (l *locker) Lock(ctx context.Context, r *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{})) (*Unlocker, context.Context, error) { +func (l *locker) Lock(ctx context.Context, r *Repository, exclusive bool, retryLock time.Duration, printRetry func(msg string), logger func(format string, args ...interface{})) (Unlocker, context.Context, error) { var lock *restic.Lock var err error @@ -102,7 +102,7 @@ retryLoop: go l.refreshLocks(ctx, repo.be, lockInfo, refreshChan, forceRefreshChan, logger) go l.monitorLockRefresh(ctx, lockInfo, refreshChan, forceRefreshChan, logger) - return &Unlocker{lockInfo}, ctx, nil + return &unlocker{lockInfo}, ctx, nil } func minDuration(a, b time.Duration) time.Duration { @@ -261,11 +261,15 @@ func tryRefreshStaleLock(ctx context.Context, be backend.Backend, lock *restic.L return true } -type Unlocker struct { +type Unlocker interface { + Unlock() +} + +type unlocker struct { info *lockContext } -func (l *Unlocker) Unlock() { +func (l *unlocker) Unlock() { l.info.cancel() l.info.refreshWG.Wait() } diff --git a/internal/repository/lock_test.go b/internal/repository/lock_test.go index c31221e42..bdfb6573b 100644 --- a/internal/repository/lock_test.go +++ b/internal/repository/lock_test.go @@ -34,11 +34,11 @@ func openLockTestRepo(t *testing.T, wrapper backendWrapper) (*Repository, backen return TestOpenBackend(t, be), be } -func checkedLockRepo(ctx context.Context, t *testing.T, repo *Repository, lockerInst *locker, retryLock time.Duration) (*Unlocker, context.Context) { +func checkedLockRepo(ctx context.Context, t *testing.T, repo *Repository, lockerInst *locker, retryLock time.Duration) (Unlocker, context.Context) { lock, wrappedCtx, err := lockerInst.Lock(ctx, repo, false, retryLock, func(msg string) {}, func(format string, args ...interface{}) {}) rtest.OK(t, err) rtest.OK(t, wrappedCtx.Err()) - if lock.info.lock.Stale() { + if lock.(*unlocker).info.lock.Stale() { t.Fatal("lock returned stale lock") } return lock, wrappedCtx