From b9bddeff393e65d0d960ebdc0d9e25a1fb551732 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Wed, 25 Jan 2017 17:48:35 +0100 Subject: [PATCH] Normalise the backend API This makes the following changes, before: type backend interface { // Test a boolean value whether a File with the name and type exists. Test(t FileType, name string) (bool, error) // Remove removes a File with type t and name. Remove(t FileType, name string) error } After: type backend interface { // Test a boolean value whether a File with the name and type exists. Test(h Handle) (bool, error) // Remove removes a File with type t and name. Remove(h Handle) error } --- src/cmds/restic/cmd_forget.go | 6 ++- src/cmds/restic/cmd_key.go | 6 ++- src/cmds/restic/cmd_prune.go | 6 ++- .../archiver/archiver_duplication_test.go | 4 +- src/restic/backend.go | 4 +- src/restic/backend/local/local.go | 12 ++--- src/restic/backend/mem/mem_backend.go | 33 ++++++-------- src/restic/backend/rest/rest.go | 7 ++- src/restic/backend/rest/rest_test.go | 2 +- src/restic/backend/s3/s3.go | 30 ++++++------- src/restic/backend/s3/s3_test.go | 2 +- src/restic/backend/sftp/sftp.go | 44 +++++++++---------- src/restic/backend/test/tests.go | 35 ++++++++------- src/restic/checker/checker.go | 3 +- src/restic/checker/checker_test.go | 23 +++++++--- src/restic/index/index_test.go | 6 ++- src/restic/lock.go | 8 ++-- src/restic/lock_test.go | 6 ++- src/restic/mock/backend.go | 12 ++--- src/restic/repository/index_rebuild.go | 3 +- src/restic/repository/repack.go | 3 +- src/restic/repository/repository.go | 2 +- 22 files changed, 139 insertions(+), 118 deletions(-) diff --git a/src/cmds/restic/cmd_forget.go b/src/cmds/restic/cmd_forget.go index e5a47d3a4..df84f2a51 100644 --- a/src/cmds/restic/cmd_forget.go +++ b/src/cmds/restic/cmd_forget.go @@ -133,7 +133,8 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error { } if !opts.DryRun { - err = repo.Backend().Remove(restic.SnapshotFile, id.String()) + h := restic.Handle{Type: restic.SnapshotFile, Name: id.String()} + err = repo.Backend().Remove(h) if err != nil { return err } @@ -201,7 +202,8 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error { if !opts.DryRun { for _, sn := range remove { - err = repo.Backend().Remove(restic.SnapshotFile, sn.ID().String()) + h := restic.Handle{Type: restic.SnapshotFile, Name: sn.ID().String()} + err = repo.Backend().Remove(h) if err != nil { return err } diff --git a/src/cmds/restic/cmd_key.go b/src/cmds/restic/cmd_key.go index 4e99f0c86..946585adf 100644 --- a/src/cmds/restic/cmd_key.go +++ b/src/cmds/restic/cmd_key.go @@ -87,7 +87,8 @@ func deleteKey(repo *repository.Repository, name string) error { return errors.Fatal("refusing to remove key currently used to access repository") } - err := repo.Backend().Remove(restic.KeyFile, name) + h := restic.Handle{Type: restic.KeyFile, Name: name} + err := repo.Backend().Remove(h) if err != nil { return err } @@ -107,7 +108,8 @@ func changePassword(gopts GlobalOptions, repo *repository.Repository) error { return errors.Fatalf("creating new key failed: %v\n", err) } - err = repo.Backend().Remove(restic.KeyFile, repo.KeyName()) + h := restic.Handle{Type: restic.KeyFile, Name: repo.KeyName()} + err = repo.Backend().Remove(h) if err != nil { return err } diff --git a/src/cmds/restic/cmd_prune.go b/src/cmds/restic/cmd_prune.go index 00f74e559..f43c99f00 100644 --- a/src/cmds/restic/cmd_prune.go +++ b/src/cmds/restic/cmd_prune.go @@ -219,7 +219,8 @@ func runPrune(gopts GlobalOptions) error { } for packID := range removePacks { - err = repo.Backend().Remove(restic.DataFile, packID.String()) + h := restic.Handle{Type: restic.DataFile, Name: packID.String()} + err = repo.Backend().Remove(h) if err != nil { Warnf("unable to remove file %v from the repository\n", packID.Str()) } @@ -239,7 +240,8 @@ func runPrune(gopts GlobalOptions) error { var supersedes restic.IDs for idxID := range repo.List(restic.IndexFile, done) { - err := repo.Backend().Remove(restic.IndexFile, idxID.String()) + h := restic.Handle{Type: restic.IndexFile, Name: idxID.String()} + err := repo.Backend().Remove(h) if err != nil { fmt.Fprintf(os.Stderr, "unable to remove index %v: %v\n", idxID.Str(), err) } diff --git a/src/restic/archiver/archiver_duplication_test.go b/src/restic/archiver/archiver_duplication_test.go index c27045bc9..c7de1cc49 100644 --- a/src/restic/archiver/archiver_duplication_test.go +++ b/src/restic/archiver/archiver_duplication_test.go @@ -39,7 +39,7 @@ func randomID() restic.ID { func forgetfulBackend() restic.Backend { be := &mock.Backend{} - be.TestFn = func(t restic.FileType, name string) (bool, error) { + be.TestFn = func(h restic.Handle) (bool, error) { return false, nil } @@ -55,7 +55,7 @@ func forgetfulBackend() restic.Backend { return restic.FileInfo{}, errors.New("not found") } - be.RemoveFn = func(t restic.FileType, name string) error { + be.RemoveFn = func(h restic.Handle) error { return nil } diff --git a/src/restic/backend.go b/src/restic/backend.go index 0db225d59..4f776b167 100644 --- a/src/restic/backend.go +++ b/src/restic/backend.go @@ -9,10 +9,10 @@ type Backend interface { Location() string // Test a boolean value whether a File with the name and type exists. - Test(t FileType, name string) (bool, error) + Test(h Handle) (bool, error) // Remove removes a File with type t and name. - Remove(t FileType, name string) error + Remove(h Handle) error // Close the backend Close() error diff --git a/src/restic/backend/local/local.go b/src/restic/backend/local/local.go index 4f7dbfdb8..03d812d99 100644 --- a/src/restic/backend/local/local.go +++ b/src/restic/backend/local/local.go @@ -219,9 +219,9 @@ func (b *Local) Stat(h restic.Handle) (restic.FileInfo, error) { } // Test returns true if a blob of the given type and name exists in the backend. -func (b *Local) Test(t restic.FileType, name string) (bool, error) { - debug.Log("Test %v %v", t, name) - _, err := fs.Stat(filename(b.p, t, name)) +func (b *Local) Test(h restic.Handle) (bool, error) { + debug.Log("Test %v", h) + _, err := fs.Stat(filename(b.p, h.Type, h.Name)) if err != nil { if os.IsNotExist(errors.Cause(err)) { return false, nil @@ -233,9 +233,9 @@ func (b *Local) Test(t restic.FileType, name string) (bool, error) { } // Remove removes the blob with the given name and type. -func (b *Local) Remove(t restic.FileType, name string) error { - debug.Log("Remove %v %v", t, name) - fn := filename(b.p, t, name) +func (b *Local) Remove(h restic.Handle) error { + debug.Log("Remove %v", h) + fn := filename(b.p, h.Type, h.Name) // reset read-only flag err := fs.Chmod(fn, 0666) diff --git a/src/restic/backend/mem/mem_backend.go b/src/restic/backend/mem/mem_backend.go index 76a00b7fe..3e96f6a36 100644 --- a/src/restic/backend/mem/mem_backend.go +++ b/src/restic/backend/mem/mem_backend.go @@ -13,12 +13,7 @@ import ( "restic/debug" ) -type entry struct { - Type restic.FileType - Name string -} - -type memMap map[entry][]byte +type memMap map[restic.Handle][]byte // make sure that MemoryBackend implements backend.Backend var _ restic.Backend = &MemoryBackend{} @@ -42,13 +37,13 @@ func New() *MemoryBackend { } // Test returns whether a file exists. -func (be *MemoryBackend) Test(t restic.FileType, name string) (bool, error) { +func (be *MemoryBackend) Test(h restic.Handle) (bool, error) { be.m.Lock() defer be.m.Unlock() - debug.Log("test %v %v", t, name) + debug.Log("Test %v", h) - if _, ok := be.data[entry{t, name}]; ok { + if _, ok := be.data[h]; ok { return true, nil } @@ -68,7 +63,7 @@ func (be *MemoryBackend) Save(h restic.Handle, rd io.Reader) error { h.Name = "" } - if _, ok := be.data[entry{h.Type, h.Name}]; ok { + if _, ok := be.data[h]; ok { return errors.New("file already exists") } @@ -77,7 +72,7 @@ func (be *MemoryBackend) Save(h restic.Handle, rd io.Reader) error { return err } - be.data[entry{h.Type, h.Name}] = buf + be.data[h] = buf debug.Log("saved %v bytes at %v", len(buf), h) return nil @@ -104,11 +99,11 @@ func (be *MemoryBackend) Load(h restic.Handle, length int, offset int64) (io.Rea return nil, errors.New("offset is negative") } - if _, ok := be.data[entry{h.Type, h.Name}]; !ok { + if _, ok := be.data[h]; !ok { return nil, errors.New("no such data") } - buf := be.data[entry{h.Type, h.Name}] + buf := be.data[h] if offset > int64(len(buf)) { return nil, errors.New("offset beyond end of file") } @@ -118,7 +113,7 @@ func (be *MemoryBackend) Load(h restic.Handle, length int, offset int64) (io.Rea buf = buf[:length] } - return backend.Closer{bytes.NewReader(buf)}, nil + return backend.Closer{Reader: bytes.NewReader(buf)}, nil } // Stat returns information about a file in the backend. @@ -136,7 +131,7 @@ func (be *MemoryBackend) Stat(h restic.Handle) (restic.FileInfo, error) { debug.Log("stat %v", h) - e, ok := be.data[entry{h.Type, h.Name}] + e, ok := be.data[h] if !ok { return restic.FileInfo{}, errors.New("no such data") } @@ -145,17 +140,17 @@ func (be *MemoryBackend) Stat(h restic.Handle) (restic.FileInfo, error) { } // Remove deletes a file from the backend. -func (be *MemoryBackend) Remove(t restic.FileType, name string) error { +func (be *MemoryBackend) Remove(h restic.Handle) error { be.m.Lock() defer be.m.Unlock() - debug.Log("get %v %v", t, name) + debug.Log("Remove %v", h) - if _, ok := be.data[entry{t, name}]; !ok { + if _, ok := be.data[h]; !ok { return errors.New("no such data") } - delete(be.data, entry{t, name}) + delete(be.data, h) return nil } diff --git a/src/restic/backend/rest/rest.go b/src/restic/backend/rest/rest.go index fe931a6b9..7121de945 100644 --- a/src/restic/backend/rest/rest.go +++ b/src/restic/backend/rest/rest.go @@ -194,8 +194,8 @@ func (b *restBackend) Stat(h restic.Handle) (restic.FileInfo, error) { } // Test returns true if a blob of the given type and name exists in the backend. -func (b *restBackend) Test(t restic.FileType, name string) (bool, error) { - _, err := b.Stat(restic.Handle{Type: t, Name: name}) +func (b *restBackend) Test(h restic.Handle) (bool, error) { + _, err := b.Stat(h) if err != nil { return false, nil } @@ -204,8 +204,7 @@ func (b *restBackend) Test(t restic.FileType, name string) (bool, error) { } // Remove removes the blob with the given name and type. -func (b *restBackend) Remove(t restic.FileType, name string) error { - h := restic.Handle{Type: t, Name: name} +func (b *restBackend) Remove(h restic.Handle) error { if err := h.Valid(); err != nil { return err } diff --git a/src/restic/backend/rest/rest_test.go b/src/restic/backend/rest/rest_test.go index 2e7095b29..af7154ebf 100644 --- a/src/restic/backend/rest/rest_test.go +++ b/src/restic/backend/rest/rest_test.go @@ -37,7 +37,7 @@ func init() { return nil, err } - exists, err := be.Test(restic.ConfigFile, "") + exists, err := be.Test(restic.Handle{Type: restic.ConfigFile, Name: ""}) if err != nil { return nil, err } diff --git a/src/restic/backend/s3/s3.go b/src/restic/backend/s3/s3.go index 00ca758eb..18f84ae70 100644 --- a/src/restic/backend/s3/s3.go +++ b/src/restic/backend/s3/s3.go @@ -55,11 +55,11 @@ func Open(cfg Config) (restic.Backend, error) { return be, nil } -func (be *s3) s3path(t restic.FileType, name string) string { - if t == restic.ConfigFile { - return path.Join(be.prefix, string(t)) +func (be *s3) s3path(h restic.Handle) string { + if h.Type == restic.ConfigFile { + return path.Join(be.prefix, string(h.Type)) } - return path.Join(be.prefix, string(t), name) + return path.Join(be.prefix, string(h.Type), h.Name) } func (be *s3) createConnections() { @@ -82,7 +82,7 @@ func (be *s3) Save(h restic.Handle, rd io.Reader) (err error) { debug.Log("Save %v", h) - objName := be.s3path(h.Type, h.Name) + objName := be.s3path(h) // Check key does not already exist _, err = be.client.StatObject(be.bucketname, objName) @@ -123,7 +123,7 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er var obj *minio.Object - objName := be.s3path(h.Type, h.Name) + objName := be.s3path(h) <-be.connChan defer func() { @@ -186,7 +186,7 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er func (be *s3) Stat(h restic.Handle) (bi restic.FileInfo, err error) { debug.Log("%v", h) - objName := be.s3path(h.Type, h.Name) + objName := be.s3path(h) var obj *minio.Object obj, err = be.client.GetObject(be.bucketname, objName) @@ -213,9 +213,9 @@ func (be *s3) Stat(h restic.Handle) (bi restic.FileInfo, err error) { } // Test returns true if a blob of the given type and name exists in the backend. -func (be *s3) Test(t restic.FileType, name string) (bool, error) { +func (be *s3) Test(h restic.Handle) (bool, error) { found := false - objName := be.s3path(t, name) + objName := be.s3path(h) _, err := be.client.StatObject(be.bucketname, objName) if err == nil { found = true @@ -226,10 +226,10 @@ func (be *s3) Test(t restic.FileType, name string) (bool, error) { } // Remove removes the blob with the given name and type. -func (be *s3) Remove(t restic.FileType, name string) error { - objName := be.s3path(t, name) +func (be *s3) Remove(h restic.Handle) error { + objName := be.s3path(h) err := be.client.RemoveObject(be.bucketname, objName) - debug.Log("%v %v -> err %v", t, name, err) + debug.Log("Remove(%v) -> err %v", h, err) return errors.Wrap(err, "client.RemoveObject") } @@ -240,7 +240,7 @@ func (be *s3) List(t restic.FileType, done <-chan struct{}) <-chan string { debug.Log("listing %v", t) ch := make(chan string) - prefix := be.s3path(t, "") + "/" + prefix := be.s3path(restic.Handle{Type: t}) + "/" listresp := be.client.ListObjects(be.bucketname, prefix, true, done) @@ -268,7 +268,7 @@ func (be *s3) removeKeys(t restic.FileType) error { done := make(chan struct{}) defer close(done) for key := range be.List(restic.DataFile, done) { - err := be.Remove(restic.DataFile, key) + err := be.Remove(restic.Handle{Type: restic.DataFile, Name: key}) if err != nil { return err } @@ -293,7 +293,7 @@ func (be *s3) Delete() error { } } - return be.Remove(restic.ConfigFile, "") + return be.Remove(restic.Handle{Type: restic.ConfigFile}) } // Close does nothing diff --git a/src/restic/backend/s3/s3_test.go b/src/restic/backend/s3/s3_test.go index 355352fa5..3bee8c8cd 100644 --- a/src/restic/backend/s3/s3_test.go +++ b/src/restic/backend/s3/s3_test.go @@ -44,7 +44,7 @@ func init() { return nil, err } - exists, err := be.Test(restic.ConfigFile, "") + exists, err := be.Test(restic.Handle{Type: restic.ConfigFile}) if err != nil { return nil, err } diff --git a/src/restic/backend/sftp/sftp.go b/src/restic/backend/sftp/sftp.go index b7f0922b6..65e6f7f73 100644 --- a/src/restic/backend/sftp/sftp.go +++ b/src/restic/backend/sftp/sftp.go @@ -259,11 +259,11 @@ func (r *SFTP) mkdirAll(dir string, mode os.FileMode) error { } // Rename temp file to final name according to type and name. -func (r *SFTP) renameFile(oldname string, t restic.FileType, name string) error { - filename := r.filename(t, name) +func (r *SFTP) renameFile(oldname string, h restic.Handle) error { + filename := r.filename(h) // create directories if necessary - if t == restic.DataFile { + if h.Type == restic.DataFile { err := r.mkdirAll(path.Dir(filename), backend.Modes.Dir) if err != nil { return err @@ -297,22 +297,22 @@ func Join(parts ...string) string { } // Construct path for given restic.Type and name. -func (r *SFTP) filename(t restic.FileType, name string) string { - if t == restic.ConfigFile { +func (r *SFTP) filename(h restic.Handle) string { + if h.Type == restic.ConfigFile { return Join(r.p, "config") } - return Join(r.dirname(t, name), name) + return Join(r.dirname(h), h.Name) } // Construct directory for given backend.Type. -func (r *SFTP) dirname(t restic.FileType, name string) string { +func (r *SFTP) dirname(h restic.Handle) string { var n string - switch t { + switch h.Type { case restic.DataFile: n = backend.Paths.Data - if len(name) > 2 { - n = Join(n, name[:2]) + if len(h.Name) > 2 { + n = Join(n, h.Name[:2]) } case restic.SnapshotFile: n = backend.Paths.Snapshots @@ -354,7 +354,7 @@ func (r *SFTP) Save(h restic.Handle, rd io.Reader) (err error) { return errors.Wrap(err, "Close") } - err = r.renameFile(filename, h.Type, h.Name) + err = r.renameFile(filename, h) debug.Log("save %v: rename %v: %v", h, path.Base(filename), err) return err @@ -373,7 +373,7 @@ func (r *SFTP) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, e return nil, errors.New("offset is negative") } - f, err := r.c.Open(r.filename(h.Type, h.Name)) + f, err := r.c.Open(r.filename(h)) if err != nil { return nil, err } @@ -395,7 +395,7 @@ func (r *SFTP) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, e // Stat returns information about a blob. func (r *SFTP) Stat(h restic.Handle) (restic.FileInfo, error) { - debug.Log("stat %v", h) + debug.Log("Stat(%v)", h) if err := r.clientError(); err != nil { return restic.FileInfo{}, err } @@ -404,7 +404,7 @@ func (r *SFTP) Stat(h restic.Handle) (restic.FileInfo, error) { return restic.FileInfo{}, err } - fi, err := r.c.Lstat(r.filename(h.Type, h.Name)) + fi, err := r.c.Lstat(r.filename(h)) if err != nil { return restic.FileInfo{}, errors.Wrap(err, "Lstat") } @@ -413,13 +413,13 @@ func (r *SFTP) Stat(h restic.Handle) (restic.FileInfo, error) { } // Test returns true if a blob of the given type and name exists in the backend. -func (r *SFTP) Test(t restic.FileType, name string) (bool, error) { - debug.Log("type %v, name %v", t, name) +func (r *SFTP) Test(h restic.Handle) (bool, error) { + debug.Log("Test(%v)", h) if err := r.clientError(); err != nil { return false, err } - _, err := r.c.Lstat(r.filename(t, name)) + _, err := r.c.Lstat(r.filename(h)) if os.IsNotExist(errors.Cause(err)) { return false, nil } @@ -432,13 +432,13 @@ func (r *SFTP) Test(t restic.FileType, name string) (bool, error) { } // Remove removes the content stored at name. -func (r *SFTP) Remove(t restic.FileType, name string) error { - debug.Log("type %v, name %v", t, name) +func (r *SFTP) Remove(h restic.Handle) error { + debug.Log("Remove(%v)", h) if err := r.clientError(); err != nil { return err } - return r.c.Remove(r.filename(t, name)) + return r.c.Remove(r.filename(h)) } // List returns a channel that yields all names of blobs of type t. A @@ -453,7 +453,7 @@ func (r *SFTP) List(t restic.FileType, done <-chan struct{}) <-chan string { if t == restic.DataFile { // read first level - basedir := r.dirname(t, "") + basedir := r.dirname(restic.Handle{Type: t}) list1, err := r.c.ReadDir(basedir) if err != nil { @@ -486,7 +486,7 @@ func (r *SFTP) List(t restic.FileType, done <-chan struct{}) <-chan string { } } } else { - entries, err := r.c.ReadDir(r.dirname(t, "")) + entries, err := r.c.ReadDir(r.dirname(restic.Handle{Type: t})) if err != nil { return } diff --git a/src/restic/backend/test/tests.go b/src/restic/backend/test/tests.go index d9241ec2b..761131a11 100644 --- a/src/restic/backend/test/tests.go +++ b/src/restic/backend/test/tests.go @@ -130,7 +130,7 @@ func TestCreateWithConfig(t testing.TB) { } // remove config - err = b.Remove(restic.ConfigFile, "") + err = b.Remove(restic.Handle{Type: restic.ConfigFile, Name: ""}) if err != nil { t.Fatalf("unexpected error removing config: %v", err) } @@ -270,7 +270,7 @@ func TestLoad(t testing.TB) { } } - test.OK(t, b.Remove(restic.DataFile, id.String())) + test.OK(t, b.Remove(handle)) } type errorCloser struct { @@ -319,7 +319,7 @@ func TestSave(t testing.TB) { t.Fatalf("Stat() returned different size, want %q, got %d", len(data), fi.Size) } - err = b.Remove(h.Type, h.Name) + err = b.Remove(h) if err != nil { t.Fatalf("error removing item: %v", err) } @@ -401,7 +401,7 @@ func TestSaveFilenames(t testing.TB) { t.Errorf("test %d: returned wrong bytes", i) } - err = b.Remove(h.Type, h.Name) + err = b.Remove(h) if err != nil { t.Errorf("test %d failed: Remove() returned %v", i, err) continue @@ -419,10 +419,12 @@ var testStrings = []struct { {"4e54d2c721cbdb730f01b10b62dec622962b36966ec685880effa63d71c808f2", "foo/../../baz"}, } -func store(t testing.TB, b restic.Backend, tpe restic.FileType, data []byte) { +func store(t testing.TB, b restic.Backend, tpe restic.FileType, data []byte) restic.Handle { id := restic.Hash(data) - err := b.Save(restic.Handle{Name: id.String(), Type: tpe}, bytes.NewReader(data)) + h := restic.Handle{Name: id.String(), Type: tpe} + err := b.Save(h, bytes.NewReader(data)) test.OK(t, err) + return h } // TestBackend tests all functions of the backend. @@ -440,12 +442,12 @@ func TestBackend(t testing.TB) { test.OK(t, err) // test if blob is already in repository - ret, err := b.Test(tpe, id.String()) + h := restic.Handle{Type: tpe, Name: id.String()} + ret, err := b.Test(h) test.OK(t, err) test.Assert(t, !ret, "blob was found to exist before creating") // try to stat a not existing blob - h := restic.Handle{Type: tpe, Name: id.String()} _, err = b.Stat(h) test.Assert(t, err != nil, "blob data could be extracted before creation") @@ -454,7 +456,7 @@ func TestBackend(t testing.TB) { test.Assert(t, err != nil, "blob reader could be obtained before creation") // try to get string out, should fail - ret, err = b.Test(tpe, id.String()) + ret, err = b.Test(h) test.OK(t, err) test.Assert(t, !ret, "id %q was found (but should not have)", ts.id) } @@ -498,16 +500,17 @@ func TestBackend(t testing.TB) { test.Assert(t, err != nil, "expected error, got %v", err) // remove and recreate - err = b.Remove(tpe, ts.id) + h := restic.Handle{Type: tpe, Name: ts.id} + err = b.Remove(h) test.OK(t, err) // test that the blob is gone - ok, err := b.Test(tpe, ts.id) + ok, err := b.Test(h) test.OK(t, err) test.Assert(t, ok == false, "removed blob still present") // create blob - err = b.Save(restic.Handle{Type: tpe, Name: ts.id}, strings.NewReader(ts.data)) + err = b.Save(h, strings.NewReader(ts.data)) test.OK(t, err) // list items @@ -542,12 +545,14 @@ func TestBackend(t testing.TB) { id, err := restic.ParseID(ts.id) test.OK(t, err) - found, err := b.Test(tpe, id.String()) + h := restic.Handle{Type: tpe, Name: id.String()} + + found, err := b.Test(h) test.OK(t, err) - test.OK(t, b.Remove(tpe, id.String())) + test.OK(t, b.Remove(h)) - found, err = b.Test(tpe, id.String()) + found, err = b.Test(h) test.OK(t, err) test.Assert(t, !found, fmt.Sprintf("id %q not found after removal", id)) } diff --git a/src/restic/checker/checker.go b/src/restic/checker/checker.go index 3b2f0787b..7b37f7dd2 100644 --- a/src/restic/checker/checker.go +++ b/src/restic/checker/checker.go @@ -187,7 +187,8 @@ func packIDTester(repo restic.Repository, inChan <-chan restic.ID, errChan chan< defer wg.Done() for id := range inChan { - ok, err := repo.Backend().Test(restic.DataFile, id.String()) + h := restic.Handle{Type: restic.DataFile, Name: id.String()} + ok, err := repo.Backend().Test(h) if err != nil { err = PackError{ID: id, Err: err} } else { diff --git a/src/restic/checker/checker_test.go b/src/restic/checker/checker_test.go index 612fc6053..d41f34b7b 100644 --- a/src/restic/checker/checker_test.go +++ b/src/restic/checker/checker_test.go @@ -73,8 +73,11 @@ func TestMissingPack(t *testing.T) { repo := repository.TestOpenLocal(t, repodir) - packID := "657f7fb64f6a854fff6fe9279998ee09034901eded4e6db9bcee0e59745bbce6" - test.OK(t, repo.Backend().Remove(restic.DataFile, packID)) + packHandle := restic.Handle{ + Type: restic.DataFile, + Name: "657f7fb64f6a854fff6fe9279998ee09034901eded4e6db9bcee0e59745bbce6", + } + test.OK(t, repo.Backend().Remove(packHandle)) chkr := checker.New(repo) hints, errs := chkr.LoadIndex() @@ -92,7 +95,7 @@ func TestMissingPack(t *testing.T) { "expected exactly one error, got %v", len(errs)) if err, ok := errs[0].(checker.PackError); ok { - test.Equals(t, packID, err.ID.String()) + test.Equals(t, packHandle.Name, err.ID.String()) } else { t.Errorf("expected error returned by checker.Packs() to be PackError, got %v", err) } @@ -105,9 +108,12 @@ func TestUnreferencedPack(t *testing.T) { repo := repository.TestOpenLocal(t, repodir) // index 3f1a only references pack 60e0 - indexID := "3f1abfcb79c6f7d0a3be517d2c83c8562fba64ef2c8e9a3544b4edaf8b5e3b44" packID := "60e0438dcb978ec6860cc1f8c43da648170ee9129af8f650f876bad19f8f788e" - test.OK(t, repo.Backend().Remove(restic.IndexFile, indexID)) + indexHandle := restic.Handle{ + Type: restic.IndexFile, + Name: "3f1abfcb79c6f7d0a3be517d2c83c8562fba64ef2c8e9a3544b4edaf8b5e3b44", + } + test.OK(t, repo.Backend().Remove(indexHandle)) chkr := checker.New(repo) hints, errs := chkr.LoadIndex() @@ -137,8 +143,11 @@ func TestUnreferencedBlobs(t *testing.T) { repo := repository.TestOpenLocal(t, repodir) - snID := "51d249d28815200d59e4be7b3f21a157b864dc343353df9d8e498220c2499b02" - test.OK(t, repo.Backend().Remove(restic.SnapshotFile, snID)) + snapshotHandle := restic.Handle{ + Type: restic.SnapshotFile, + Name: "51d249d28815200d59e4be7b3f21a157b864dc343353df9d8e498220c2499b02", + } + test.OK(t, repo.Backend().Remove(snapshotHandle)) unusedBlobsBySnapshot := restic.IDs{ restic.TestParseID("58c748bbe2929fdf30c73262bd8313fe828f8925b05d1d4a87fe109082acb849"), diff --git a/src/restic/index/index_test.go b/src/restic/index/index_test.go index 370625faf..1984c2cb6 100644 --- a/src/restic/index/index_test.go +++ b/src/restic/index/index_test.go @@ -234,7 +234,8 @@ func TestSave(t *testing.T) { for id := range idx.IndexIDs { t.Logf("remove index %v", id.Str()) - err = repo.Backend().Remove(restic.IndexFile, id.String()) + h := restic.Handle{Type: restic.IndexFile, Name: id.String()} + err = repo.Backend().Remove(h) if err != nil { t.Errorf("error removing index %v: %v", id, err) } @@ -275,7 +276,8 @@ func TestIndexSave(t *testing.T) { for id := range idx.IndexIDs { t.Logf("remove index %v", id.Str()) - err = repo.Backend().Remove(restic.IndexFile, id.String()) + h := restic.Handle{Type: restic.IndexFile, Name: id.String()} + err = repo.Backend().Remove(h) if err != nil { t.Errorf("error removing index %v: %v", id, err) } diff --git a/src/restic/lock.go b/src/restic/lock.go index e5f4a4b84..8fec7535b 100644 --- a/src/restic/lock.go +++ b/src/restic/lock.go @@ -186,7 +186,7 @@ func (l *Lock) Unlock() error { return nil } - return l.repo.Backend().Remove(LockFile, l.lockID.String()) + return l.repo.Backend().Remove(Handle{Type: LockFile, Name: l.lockID.String()}) } var staleTimeout = 30 * time.Minute @@ -234,7 +234,7 @@ func (l *Lock) Refresh() error { return err } - err = l.repo.Backend().Remove(LockFile, l.lockID.String()) + err = l.repo.Backend().Remove(Handle{Type: LockFile, Name: l.lockID.String()}) if err != nil { return err } @@ -289,7 +289,7 @@ func RemoveStaleLocks(repo Repository) error { } if lock.Stale() { - return repo.Backend().Remove(LockFile, id.String()) + return repo.Backend().Remove(Handle{Type: LockFile, Name: id.String()}) } return nil @@ -299,6 +299,6 @@ func RemoveStaleLocks(repo Repository) error { // RemoveAllLocks removes all locks forcefully. func RemoveAllLocks(repo Repository) error { return eachLock(repo, func(id ID, lock *Lock, err error) error { - return repo.Backend().Remove(LockFile, id.String()) + return repo.Backend().Remove(Handle{Type: LockFile, Name: id.String()}) }) } diff --git a/src/restic/lock_test.go b/src/restic/lock_test.go index a6854dbe6..b8288d6cd 100644 --- a/src/restic/lock_test.go +++ b/src/restic/lock_test.go @@ -102,7 +102,8 @@ func createFakeLock(repo restic.Repository, t time.Time, pid int) (restic.ID, er } func removeLock(repo restic.Repository, id restic.ID) error { - return repo.Backend().Remove(restic.LockFile, id.String()) + h := restic.Handle{Type: restic.LockFile, Name: id.String()} + return repo.Backend().Remove(h) } var staleLockTests = []struct { @@ -162,7 +163,8 @@ func TestLockStale(t *testing.T) { } func lockExists(repo restic.Repository, t testing.TB, id restic.ID) bool { - exists, err := repo.Backend().Test(restic.LockFile, id.String()) + h := restic.Handle{Type: restic.LockFile, Name: id.String()} + exists, err := repo.Backend().Test(h) OK(t, err) return exists diff --git a/src/restic/mock/backend.go b/src/restic/mock/backend.go index 9c5504f1a..704e87150 100644 --- a/src/restic/mock/backend.go +++ b/src/restic/mock/backend.go @@ -14,8 +14,8 @@ type Backend struct { LoadFn func(h restic.Handle, length int, offset int64) (io.ReadCloser, error) StatFn func(h restic.Handle) (restic.FileInfo, error) ListFn func(restic.FileType, <-chan struct{}) <-chan string - RemoveFn func(restic.FileType, string) error - TestFn func(restic.FileType, string) (bool, error) + RemoveFn func(h restic.Handle) error + TestFn func(h restic.Handle) (bool, error) DeleteFn func() error LocationFn func() string } @@ -77,21 +77,21 @@ func (m *Backend) List(t restic.FileType, done <-chan struct{}) <-chan string { } // Remove data from the backend. -func (m *Backend) Remove(t restic.FileType, name string) error { +func (m *Backend) Remove(h restic.Handle) error { if m.RemoveFn == nil { return errors.New("not implemented") } - return m.RemoveFn(t, name) + return m.RemoveFn(h) } // Test for the existence of a specific item. -func (m *Backend) Test(t restic.FileType, name string) (bool, error) { +func (m *Backend) Test(h restic.Handle) (bool, error) { if m.TestFn == nil { return false, errors.New("not implemented") } - return m.TestFn(t, name) + return m.TestFn(h) } // Delete all data. diff --git a/src/restic/repository/index_rebuild.go b/src/restic/repository/index_rebuild.go index 592ac04ec..fcfc3027f 100644 --- a/src/restic/repository/index_rebuild.go +++ b/src/restic/repository/index_rebuild.go @@ -55,7 +55,8 @@ func RebuildIndex(repo restic.Repository) error { debug.Log("new index saved as %v", id.Str()) for indexID := range oldIndexes { - err := repo.Backend().Remove(restic.IndexFile, indexID.String()) + h := restic.Handle{Type: restic.IndexFile, Name: indexID.String()} + err := repo.Backend().Remove(h) if err != nil { fmt.Fprintf(os.Stderr, "unable to remove index %v: %v\n", indexID.Str(), err) } diff --git a/src/restic/repository/repack.go b/src/restic/repository/repack.go index f58932ff6..59bc70b68 100644 --- a/src/restic/repository/repack.go +++ b/src/restic/repository/repack.go @@ -123,7 +123,8 @@ func Repack(repo restic.Repository, packs restic.IDSet, keepBlobs restic.BlobSet } for packID := range packs { - err := repo.Backend().Remove(restic.DataFile, packID.String()) + h := restic.Handle{Type: restic.DataFile, Name: packID.String()} + err := repo.Backend().Remove(h) if err != nil { debug.Log("error removing pack %v: %v", packID.Str(), err) return err diff --git a/src/restic/repository/repository.go b/src/restic/repository/repository.go index 6cf70d1a4..45046dac2 100644 --- a/src/restic/repository/repository.go +++ b/src/restic/repository/repository.go @@ -380,7 +380,7 @@ func (r *Repository) SearchKey(password string, maxKeys int) error { // Init creates a new master key with the supplied password, initializes and // saves the repository config. func (r *Repository) Init(password string) error { - has, err := r.be.Test(restic.ConfigFile, "") + has, err := r.be.Test(restic.Handle{Type: restic.ConfigFile}) if err != nil { return err }