2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-26 14:56:29 +00:00

Merge pull request #749 from restic/normalise-backend-api

Normalise the backend API
This commit is contained in:
Alexander Neumann 2017-01-27 13:30:30 +01:00
commit b2d00b2a86
22 changed files with 140 additions and 119 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
@ -360,7 +360,7 @@ func TestSave(t testing.TB) {
t.Fatal(err)
}
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))
}

View File

@ -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 {

View File

@ -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"),

View File

@ -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)
}

View File

@ -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()})
})
}

View File

@ -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

View File

@ -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.

View File

@ -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)
}

View File

@ -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

View File

@ -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
}