mirror of https://github.com/restic/restic.git
Merge pull request #749 from restic/normalise-backend-api
Normalise the backend API
This commit is contained in:
commit
b2d00b2a86
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue