diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index a94ad138b..c3ba1dd83 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -9,8 +9,8 @@ import ( ) type CmdCheck struct { - ReadData bool `long:"read-data" description:"Read data blobs" default:"false"` - CheckUnused bool `long:"check-unused" description:"Check for unused blobs" default:"false"` + ReadData bool `long:"read-data" default:"false" description:"Read data blobs"` + CheckUnused bool `long:"check-unused" default:"false" description:"Check for unused blobs"` global *GlobalOptions } @@ -39,11 +39,13 @@ func (cmd CmdCheck) Execute(args []string) error { return err } - cmd.global.Verbosef("Create exclusive lock for repository\n") - lock, err := lockRepoExclusive(repo) - defer unlockRepo(lock) - if err != nil { - return err + if !cmd.global.NoLock { + cmd.global.Verbosef("Create exclusive lock for repository\n") + lock, err := lockRepoExclusive(repo) + defer unlockRepo(lock) + if err != nil { + return err + } } chkr := checker.New(repo) diff --git a/cmd/restic/cmd_list.go b/cmd/restic/cmd_list.go index 11f4bd8d6..fc13ff5a1 100644 --- a/cmd/restic/cmd_list.go +++ b/cmd/restic/cmd_list.go @@ -35,10 +35,12 @@ func (cmd CmdList) Execute(args []string) error { return err } - lock, err := lockRepo(repo) - defer unlockRepo(lock) - if err != nil { - return err + if !cmd.global.NoLock { + lock, err := lockRepo(repo) + defer unlockRepo(lock) + if err != nil { + return err + } } var t backend.Type diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index 26ef9b9e0..0daf74966 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -53,10 +53,12 @@ func (cmd CmdRestore) Execute(args []string) error { return err } - lock, err := lockRepo(repo) - defer unlockRepo(lock) - if err != nil { - return err + if !cmd.global.NoLock { + lock, err := lockRepo(repo) + defer unlockRepo(lock) + if err != nil { + return err + } } err = repo.LoadIndex() diff --git a/cmd/restic/global.go b/cmd/restic/global.go index 7b59de9ed..7de028c3c 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -24,6 +24,7 @@ type GlobalOptions struct { Repo string `short:"r" long:"repo" description:"Repository directory to backup to/restore from"` CacheDir string ` long:"cache-dir" description:"Directory to use as a local cache"` Quiet bool `short:"q" long:"quiet" default:"false" description:"Do not output comprehensive progress report"` + NoLock bool ` long:"no-lock" default:"false" description:"Do not lock the repo, this allows some operations on read-only repos."` password string stdout io.Writer diff --git a/cmd/restic/integration_test.go b/cmd/restic/integration_test.go index 8d01849eb..bc734bf0a 100644 --- a/cmd/restic/integration_test.go +++ b/cmd/restic/integration_test.go @@ -62,14 +62,15 @@ func cmdBackupExcludes(t testing.TB, global GlobalOptions, target []string, pare } func cmdList(t testing.TB, global GlobalOptions, tpe string) backend.IDs { - var buf bytes.Buffer - global.stdout = &buf cmd := &CmdList{global: &global} + return executeAndParseIDs(t, cmd, tpe) +} - OK(t, cmd.Execute([]string{tpe})) - IDs := parseIDsFromReader(t, &buf) - - return IDs +func executeAndParseIDs(t testing.TB, cmd *CmdList, args ...string) backend.IDs { + buf := bytes.NewBuffer(nil) + cmd.global.stdout = buf + OK(t, cmd.Execute(args)) + return parseIDsFromReader(t, buf) } func cmdRestore(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) { @@ -788,3 +789,28 @@ func TestOptimizeRemoveUnusedBlobs(t *testing.T) { }) } } + +func TestCheckRestoreNoLock(t *testing.T) { + withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) { + datafile := filepath.Join("testdata", "small-repo.tar.gz") + SetupTarTestFixture(t, env.base, datafile) + + err := filepath.Walk(env.repo, func(p string, fi os.FileInfo, e error) error { + if e != nil { + return e + } + return os.Chmod(p, fi.Mode() & ^(os.FileMode(0222))) + }) + OK(t, err) + + global.NoLock = true + cmdCheck(t, global) + + snapshotIDs := cmdList(t, global, "snapshots") + if len(snapshotIDs) == 0 { + t.Fatalf("found no snapshots") + } + + cmdRestore(t, global, filepath.Join(env.base, "restore"), snapshotIDs[0]) + }) +} diff --git a/cmd/restic/testdata/small-repo.tar.gz b/cmd/restic/testdata/small-repo.tar.gz new file mode 100644 index 000000000..83959f539 Binary files /dev/null and b/cmd/restic/testdata/small-repo.tar.gz differ