From b80aa7b1cc0bdbf4911d3776b04f6fb2eb900a5b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Thu, 13 Jun 2024 20:00:20 +0200 Subject: [PATCH] repository: prevent initialization if a snapshot exists --- internal/repository/repository.go | 9 +++++++++ internal/repository/repository_test.go | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 775ff7964..838858c38 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -780,6 +780,15 @@ func (r *Repository) Init(ctx context.Context, version uint, password string, ch }); err != nil { return err } + // Also check for snapshots to detect repositories with a misconfigured retention + // policy that deletes files older than x days. For such repositories usually the + // config and key files are removed first and therefore the check would not detect + // the old repository. + if err := r.List(ctx, restic.SnapshotFile, func(_ restic.ID, _ int64) error { + return errors.New("repository already contains snapshots") + }); err != nil { + return err + } cfg, err := restic.CreateConfig(version) if err != nil { diff --git a/internal/repository/repository_test.go b/internal/repository/repository_test.go index 0c04319d6..ea21ea3f3 100644 --- a/internal/repository/repository_test.go +++ b/internal/repository/repository_test.go @@ -473,4 +473,14 @@ func TestNoDoubleInit(t *testing.T) { rtest.OK(t, be.Remove(context.TODO(), backend.Handle{Type: backend.ConfigFile})) err = repo.Init(context.TODO(), r.Config().Version, test.TestPassword, &pol) rtest.Assert(t, strings.Contains(err.Error(), "repository already contains keys"), "expected already contains keys error, got %q", err) + + // must also prevent init if a snapshot exists and keys were deleted + var data [32]byte + hash := restic.Hash(data[:]) + rtest.OK(t, be.Save(context.TODO(), backend.Handle{Type: backend.SnapshotFile, Name: hash.String()}, backend.NewByteReader(data[:], be.Hasher()))) + rtest.OK(t, be.List(context.TODO(), restic.KeyFile, func(fi backend.FileInfo) error { + return be.Remove(context.TODO(), backend.Handle{Type: restic.KeyFile, Name: fi.Name}) + })) + err = repo.Init(context.TODO(), r.Config().Version, test.TestPassword, &pol) + rtest.Assert(t, strings.Contains(err.Error(), "repository already contains snapshots"), "expected already contains snapshots error, got %q", err) }