diff --git a/changelog/0.8.4/issue-1652 b/changelog/0.8.4/issue-1652 new file mode 100644 index 000000000..aefad7912 --- /dev/null +++ b/changelog/0.8.4/issue-1652 @@ -0,0 +1,9 @@ +Bugfix: Ignore/remove invalid lock files + +This corrects a bug introduced recently: When an invalid lock file in the repo +is encountered (e.g. if the file is empty), the code used to ignore that, but +now returns the error. Now, invalid files are ignored for the normal lock +check, and removed when `restic unlock --remove-all` is run. + +https://github.com/restic/restic/issues/1652 +https://github.com/restic/restic/pull/1653 diff --git a/internal/restic/lock.go b/internal/restic/lock.go index d3e5edc57..3e3a27a6b 100644 --- a/internal/restic/lock.go +++ b/internal/restic/lock.go @@ -138,13 +138,15 @@ func (l *Lock) fillUserInfo() error { // non-exclusive lock is to be created, an error is only returned when an // exclusive lock is found. func (l *Lock) checkForOtherLocks(ctx context.Context) error { - return eachLock(ctx, l.repo, func(id ID, lock *Lock, err error) error { + return l.repo.List(ctx, LockFile, func(id ID, size int64) error { if l.lockID != nil && id.Equal(*l.lockID) { return nil } - // ignore locks that cannot be loaded + lock, err := LoadLock(ctx, l.repo, id) if err != nil { + // ignore locks that cannot be loaded + debug.Log("ignore lock %v: %v", id, err) return nil } @@ -160,17 +162,6 @@ func (l *Lock) checkForOtherLocks(ctx context.Context) error { }) } -func eachLock(ctx context.Context, repo Repository, f func(ID, *Lock, error) error) error { - return repo.List(ctx, LockFile, func(id ID, size int64) error { - lock, err := LoadLock(ctx, repo, id) - if err != nil { - return err - } - - return f(id, lock, err) - }) -} - // createLock acquires the lock by creating a file in the repository. func (l *Lock) createLock(ctx context.Context) (ID, error) { id, err := l.repo.SaveJSONUnpacked(ctx, LockFile, l) @@ -283,9 +274,11 @@ func LoadLock(ctx context.Context, repo Repository, id ID) (*Lock, error) { // RemoveStaleLocks deletes all locks detected as stale from the repository. func RemoveStaleLocks(ctx context.Context, repo Repository) error { - return eachLock(ctx, repo, func(id ID, lock *Lock, err error) error { - // ignore locks that cannot be loaded + return repo.List(ctx, LockFile, func(id ID, size int64) error { + lock, err := LoadLock(ctx, repo, id) if err != nil { + // ignore locks that cannot be loaded + debug.Log("ignore lock %v: %v", id, err) return nil } @@ -299,7 +292,7 @@ func RemoveStaleLocks(ctx context.Context, repo Repository) error { // RemoveAllLocks removes all locks forcefully. func RemoveAllLocks(ctx context.Context, repo Repository) error { - return eachLock(ctx, repo, func(id ID, lock *Lock, err error) error { + return repo.List(ctx, LockFile, func(id ID, size int64) error { return repo.Backend().Remove(context.TODO(), Handle{Type: LockFile, Name: id.String()}) }) }