From c79dcbd7c47a86d0b37bd50b7f755ffd67467c91 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 10 Nov 2015 21:41:22 +0100 Subject: [PATCH 1/3] Allow checking a read-only repo with --no-lock --- cmd/restic/cmd_check.go | 17 ++++++++++------- cmd/restic/integration_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index a94ad138b..3e437b315 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -9,8 +9,9 @@ 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"` + NoLock bool `long:"no-lock" default:"false" description:"Do not lock repository, this allows checking read-only"` global *GlobalOptions } @@ -39,11 +40,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.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/integration_test.go b/cmd/restic/integration_test.go index 8d01849eb..3cbfde18a 100644 --- a/cmd/restic/integration_test.go +++ b/cmd/restic/integration_test.go @@ -103,6 +103,16 @@ func cmdCheckOutput(t testing.TB, global GlobalOptions) string { return string(buf.Bytes()) } +func cmdCheckNoLock(t testing.TB, global GlobalOptions) { + cmd := &CmdCheck{ + global: &global, + ReadData: true, + CheckUnused: true, + NoLock: true, + } + OK(t, cmd.Execute(nil)) +} + func cmdRebuildIndex(t testing.TB, global GlobalOptions) { global.stdout = ioutil.Discard cmd := &CmdRebuildIndex{global: &global} @@ -788,3 +798,20 @@ func TestOptimizeRemoveUnusedBlobs(t *testing.T) { }) } } + +func TestCheckRestoreNoLock(t *testing.T) { + withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) { + datafile := filepath.Join("testdata", "repo-restore-permissions-test.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) + + cmdCheckNoLock(t, global) + }) +} From 6edb7e02d03bd38034b9992449d99c235e353244 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 10 Nov 2015 22:13:53 +0100 Subject: [PATCH 2/3] Allow restoring and listing without locking --- cmd/restic/cmd_list.go | 12 +++++++---- cmd/restic/cmd_restore.go | 11 ++++++---- cmd/restic/integration_test.go | 30 ++++++++++++++++++++------ cmd/restic/testdata/small-repo.tar.gz | Bin 0 -> 9042 bytes 4 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 cmd/restic/testdata/small-repo.tar.gz diff --git a/cmd/restic/cmd_list.go b/cmd/restic/cmd_list.go index 11f4bd8d6..6883eae61 100644 --- a/cmd/restic/cmd_list.go +++ b/cmd/restic/cmd_list.go @@ -8,6 +8,8 @@ import ( ) type CmdList struct { + NoLock bool `long:"no-lock" default:"false" description:"Do not lock repository, this allows listing a read-only repo"` + global *GlobalOptions } @@ -35,10 +37,12 @@ func (cmd CmdList) Execute(args []string) error { return err } - lock, err := lockRepo(repo) - defer unlockRepo(lock) - if err != nil { - return err + if !cmd.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..389d0b5cc 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -13,6 +13,7 @@ type CmdRestore struct { Exclude []string `short:"e" long:"exclude" description:"Exclude a pattern (can be specified multiple times)"` Include []string `short:"i" long:"include" description:"Include a pattern, exclude everything else (can be specified multiple times)"` Target string `short:"t" long:"target" description:"Directory to restore to"` + NoLock bool ` long:"no-lock" default:"false" description:"Do not lock repository, this allows restoring a read-only repo"` global *GlobalOptions } @@ -53,10 +54,12 @@ func (cmd CmdRestore) Execute(args []string) error { return err } - lock, err := lockRepo(repo) - defer unlockRepo(lock) - if err != nil { - return err + if !cmd.NoLock { + lock, err := lockRepo(repo) + defer unlockRepo(lock) + if err != nil { + return err + } } err = repo.LoadIndex() diff --git a/cmd/restic/integration_test.go b/cmd/restic/integration_test.go index 3cbfde18a..21e118d60 100644 --- a/cmd/restic/integration_test.go +++ b/cmd/restic/integration_test.go @@ -62,20 +62,31 @@ 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) +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) +} - return IDs +func cmdListNoLock(t testing.TB, global GlobalOptions, tpe string) backend.IDs { + cmd := &CmdList{global: &global, NoLock: true} + return executeAndParseIDs(t, cmd, tpe) } func cmdRestore(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) { cmdRestoreExcludes(t, global, dir, snapshotID, nil) } +func cmdRestoreNoLock(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) { + cmd := &CmdRestore{global: &global, Target: dir, NoLock: true} + OK(t, cmd.Execute([]string{snapshotID.String()})) +} + func cmdRestoreExcludes(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID, excludes []string) { cmd := &CmdRestore{global: &global, Target: dir, Exclude: excludes} OK(t, cmd.Execute([]string{snapshotID.String()})) @@ -801,7 +812,7 @@ func TestOptimizeRemoveUnusedBlobs(t *testing.T) { func TestCheckRestoreNoLock(t *testing.T) { withTestEnvironment(t, func(env *testEnvironment, global GlobalOptions) { - datafile := filepath.Join("testdata", "repo-restore-permissions-test.tar.gz") + 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 { @@ -813,5 +824,12 @@ func TestCheckRestoreNoLock(t *testing.T) { OK(t, err) cmdCheckNoLock(t, global) + + snapshotIDs := cmdListNoLock(t, global, "snapshots") + if len(snapshotIDs) == 0 { + t.Fatalf("found no snapshots") + } + + cmdRestoreNoLock(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 0000000000000000000000000000000000000000..83959f539b19f6d8f9270fecba960726046d9db9 GIT binary patch literal 9042 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 Date: Fri, 13 Nov 2015 12:33:59 +0100 Subject: [PATCH 3/3] Make NoLock a global option --- cmd/restic/cmd_check.go | 3 +-- cmd/restic/cmd_list.go | 4 +--- cmd/restic/cmd_restore.go | 3 +-- cmd/restic/global.go | 1 + cmd/restic/integration_test.go | 27 ++++----------------------- 5 files changed, 8 insertions(+), 30 deletions(-) diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 3e437b315..c3ba1dd83 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -11,7 +11,6 @@ import ( type CmdCheck struct { ReadData bool `long:"read-data" default:"false" description:"Read data blobs"` CheckUnused bool `long:"check-unused" default:"false" description:"Check for unused blobs"` - NoLock bool `long:"no-lock" default:"false" description:"Do not lock repository, this allows checking read-only"` global *GlobalOptions } @@ -40,7 +39,7 @@ func (cmd CmdCheck) Execute(args []string) error { return err } - if !cmd.NoLock { + if !cmd.global.NoLock { cmd.global.Verbosef("Create exclusive lock for repository\n") lock, err := lockRepoExclusive(repo) defer unlockRepo(lock) diff --git a/cmd/restic/cmd_list.go b/cmd/restic/cmd_list.go index 6883eae61..fc13ff5a1 100644 --- a/cmd/restic/cmd_list.go +++ b/cmd/restic/cmd_list.go @@ -8,8 +8,6 @@ import ( ) type CmdList struct { - NoLock bool `long:"no-lock" default:"false" description:"Do not lock repository, this allows listing a read-only repo"` - global *GlobalOptions } @@ -37,7 +35,7 @@ func (cmd CmdList) Execute(args []string) error { return err } - if !cmd.NoLock { + if !cmd.global.NoLock { lock, err := lockRepo(repo) defer unlockRepo(lock) if err != nil { diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index 389d0b5cc..0daf74966 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -13,7 +13,6 @@ type CmdRestore struct { Exclude []string `short:"e" long:"exclude" description:"Exclude a pattern (can be specified multiple times)"` Include []string `short:"i" long:"include" description:"Include a pattern, exclude everything else (can be specified multiple times)"` Target string `short:"t" long:"target" description:"Directory to restore to"` - NoLock bool ` long:"no-lock" default:"false" description:"Do not lock repository, this allows restoring a read-only repo"` global *GlobalOptions } @@ -54,7 +53,7 @@ func (cmd CmdRestore) Execute(args []string) error { return err } - if !cmd.NoLock { + if !cmd.global.NoLock { lock, err := lockRepo(repo) defer unlockRepo(lock) if err != nil { 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 21e118d60..bc734bf0a 100644 --- a/cmd/restic/integration_test.go +++ b/cmd/restic/integration_test.go @@ -73,20 +73,10 @@ func executeAndParseIDs(t testing.TB, cmd *CmdList, args ...string) backend.IDs return parseIDsFromReader(t, buf) } -func cmdListNoLock(t testing.TB, global GlobalOptions, tpe string) backend.IDs { - cmd := &CmdList{global: &global, NoLock: true} - return executeAndParseIDs(t, cmd, tpe) -} - func cmdRestore(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) { cmdRestoreExcludes(t, global, dir, snapshotID, nil) } -func cmdRestoreNoLock(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) { - cmd := &CmdRestore{global: &global, Target: dir, NoLock: true} - OK(t, cmd.Execute([]string{snapshotID.String()})) -} - func cmdRestoreExcludes(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID, excludes []string) { cmd := &CmdRestore{global: &global, Target: dir, Exclude: excludes} OK(t, cmd.Execute([]string{snapshotID.String()})) @@ -114,16 +104,6 @@ func cmdCheckOutput(t testing.TB, global GlobalOptions) string { return string(buf.Bytes()) } -func cmdCheckNoLock(t testing.TB, global GlobalOptions) { - cmd := &CmdCheck{ - global: &global, - ReadData: true, - CheckUnused: true, - NoLock: true, - } - OK(t, cmd.Execute(nil)) -} - func cmdRebuildIndex(t testing.TB, global GlobalOptions) { global.stdout = ioutil.Discard cmd := &CmdRebuildIndex{global: &global} @@ -823,13 +803,14 @@ func TestCheckRestoreNoLock(t *testing.T) { }) OK(t, err) - cmdCheckNoLock(t, global) + global.NoLock = true + cmdCheck(t, global) - snapshotIDs := cmdListNoLock(t, global, "snapshots") + snapshotIDs := cmdList(t, global, "snapshots") if len(snapshotIDs) == 0 { t.Fatalf("found no snapshots") } - cmdRestoreNoLock(t, global, filepath.Join(env.base, "restore"), snapshotIDs[0]) + cmdRestore(t, global, filepath.Join(env.base, "restore"), snapshotIDs[0]) }) }