forked from TrueCloudLab/restic
backend: remove Test method
The Test method was only used in exactly one place, namely when trying to create a new repository it was used to check whether a config file already exists. Use a combination of Stat() and IsNotExist() instead.
This commit is contained in:
parent
57d8eedb88
commit
40ac678252
24 changed files with 47 additions and 230 deletions
|
@ -1873,10 +1873,6 @@ type noCancelBackend struct {
|
||||||
restic.Backend
|
restic.Backend
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *noCancelBackend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
return c.Backend.Test(context.Background(), h)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *noCancelBackend) Remove(ctx context.Context, h restic.Handle) error {
|
func (c *noCancelBackend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
return c.Backend.Remove(context.Background(), h)
|
return c.Backend.Remove(context.Background(), h)
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,20 +330,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo,
|
||||||
return fi, nil
|
return fi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (be *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
objName := be.Filename(h)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
found, err := be.container.GetBlobReference(objName).Exists()
|
|
||||||
be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
|
|
@ -51,12 +51,12 @@ func newAzureTestSuite(t testing.TB) *test.Suite {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := be.Test(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,12 +147,12 @@ func Create(ctx context.Context, cfg Config, rt http.RoundTripper) (restic.Backe
|
||||||
sem: sem,
|
sem: sem,
|
||||||
}
|
}
|
||||||
|
|
||||||
present, err := be.Test(ctx, restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(ctx, restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if present {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,23 +287,6 @@ func (be *b2Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileI
|
||||||
return restic.FileInfo{Size: info.Size, Name: h.Name}, nil
|
return restic.FileInfo{Size: info.Size, Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (be *b2Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
debug.Log("Test %v", h)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
defer be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
found := false
|
|
||||||
name := be.Filename(h)
|
|
||||||
obj := be.bucket.Object(name)
|
|
||||||
info, err := obj.Attrs(ctx)
|
|
||||||
if err == nil && info != nil && info.Status == b2.Uploaded {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (be *b2Backend) Remove(ctx context.Context, h restic.Handle) error {
|
func (be *b2Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
debug.Log("Remove %v", h)
|
debug.Log("Remove %v", h)
|
||||||
|
|
|
@ -86,7 +86,3 @@ func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
|
||||||
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
|
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
|
||||||
return be.b.Stat(ctx, h)
|
return be.b.Stat(ctx, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (be *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
return be.b.Test(ctx, h)
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,12 +41,9 @@ func TestDry(t *testing.T) {
|
||||||
{d, "stat", "a", "", "not found"},
|
{d, "stat", "a", "", "not found"},
|
||||||
{d, "list", "", "", ""},
|
{d, "list", "", "", ""},
|
||||||
{d, "save", "", "", "invalid"},
|
{d, "save", "", "", "invalid"},
|
||||||
{d, "test", "a", "", ""},
|
|
||||||
{m, "save", "a", "baz", ""}, // save a directly to the mem backend
|
{m, "save", "a", "baz", ""}, // save a directly to the mem backend
|
||||||
{d, "save", "b", "foob", ""}, // b is not saved
|
{d, "save", "b", "foob", ""}, // b is not saved
|
||||||
{d, "save", "b", "xxx", ""}, // no error as b is not saved
|
{d, "save", "b", "xxx", ""}, // no error as b is not saved
|
||||||
{d, "test", "a", "1", ""},
|
|
||||||
{d, "test", "b", "", ""},
|
|
||||||
{d, "stat", "", "", "invalid"},
|
{d, "stat", "", "", "invalid"},
|
||||||
{d, "stat", "a", "a 3", ""},
|
{d, "stat", "a", "a 3", ""},
|
||||||
{d, "load", "a", "baz", ""},
|
{d, "load", "a", "baz", ""},
|
||||||
|
@ -65,17 +62,11 @@ func TestDry(t *testing.T) {
|
||||||
|
|
||||||
for i, step := range steps {
|
for i, step := range steps {
|
||||||
var err error
|
var err error
|
||||||
var boolRes bool
|
|
||||||
|
|
||||||
handle := restic.Handle{Type: restic.PackFile, Name: step.fname}
|
handle := restic.Handle{Type: restic.PackFile, Name: step.fname}
|
||||||
switch step.op {
|
switch step.op {
|
||||||
case "save":
|
case "save":
|
||||||
err = step.be.Save(ctx, handle, restic.NewByteReader([]byte(step.content), step.be.Hasher()))
|
err = step.be.Save(ctx, handle, restic.NewByteReader([]byte(step.content), step.be.Hasher()))
|
||||||
case "test":
|
|
||||||
boolRes, err = step.be.Test(ctx, handle)
|
|
||||||
if boolRes != (step.content != "") {
|
|
||||||
t.Errorf("%d. Test(%q) = %v, want %v", i, step.fname, boolRes, step.content != "")
|
|
||||||
}
|
|
||||||
case "list":
|
case "list":
|
||||||
fileList := []string{}
|
fileList := []string{}
|
||||||
err = step.be.List(ctx, restic.PackFile, func(fi restic.FileInfo) error {
|
err = step.be.List(ctx, restic.PackFile, func(fi restic.FileInfo) error {
|
||||||
|
|
|
@ -329,22 +329,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
|
||||||
return restic.FileInfo{Size: attr.Size, Name: h.Name}, nil
|
return restic.FileInfo{Size: attr.Size, Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (be *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
found := false
|
|
||||||
objName := be.Filename(h)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
_, err := be.bucket.Object(objName).Attrs(ctx)
|
|
||||||
be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
// If error, then not found
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
|
|
@ -47,12 +47,12 @@ func newGSTestSuite(t testing.TB) *test.Suite {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := be.Test(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,24 +269,6 @@ func (b *Local) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, err
|
||||||
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (b *Local) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
debug.Log("Test %v", h)
|
|
||||||
|
|
||||||
b.sem.GetToken()
|
|
||||||
defer b.sem.ReleaseToken()
|
|
||||||
|
|
||||||
_, err := fs.Stat(b.Filename(h))
|
|
||||||
if err != nil {
|
|
||||||
if b.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
|
func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
debug.Log("Remove %v", h)
|
debug.Log("Remove %v", h)
|
||||||
|
|
|
@ -52,23 +52,6 @@ func New() *MemoryBackend {
|
||||||
return be
|
return be
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns whether a file exists.
|
|
||||||
func (be *MemoryBackend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
be.sem.GetToken()
|
|
||||||
defer be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
be.m.Lock()
|
|
||||||
defer be.m.Unlock()
|
|
||||||
|
|
||||||
debug.Log("Test %v", h)
|
|
||||||
|
|
||||||
if _, ok := be.data[h]; ok {
|
|
||||||
return true, ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotExist returns true if the file does not exist.
|
// IsNotExist returns true if the file does not exist.
|
||||||
func (be *MemoryBackend) IsNotExist(err error) bool {
|
func (be *MemoryBackend) IsNotExist(err error) bool {
|
||||||
return errors.Is(err, errNotFound)
|
return errors.Is(err, errNotFound)
|
||||||
|
|
|
@ -26,12 +26,12 @@ func newTestSuite() *test.Suite {
|
||||||
Create: func(cfg interface{}) (restic.Backend, error) {
|
Create: func(cfg interface{}) (restic.Backend, error) {
|
||||||
c := cfg.(*memConfig)
|
c := cfg.(*memConfig)
|
||||||
if c.be != nil {
|
if c.be != nil {
|
||||||
ok, err := c.be.Test(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
_, err := c.be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !c.be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ type Backend struct {
|
||||||
StatFn func(ctx context.Context, h restic.Handle) (restic.FileInfo, error)
|
StatFn func(ctx context.Context, h restic.Handle) (restic.FileInfo, error)
|
||||||
ListFn func(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error
|
ListFn func(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error
|
||||||
RemoveFn func(ctx context.Context, h restic.Handle) error
|
RemoveFn func(ctx context.Context, h restic.Handle) error
|
||||||
TestFn func(ctx context.Context, h restic.Handle) (bool, error)
|
|
||||||
DeleteFn func(ctx context.Context) error
|
DeleteFn func(ctx context.Context) error
|
||||||
ConnectionsFn func() uint
|
ConnectionsFn func() uint
|
||||||
LocationFn func() string
|
LocationFn func() string
|
||||||
|
@ -143,15 +142,6 @@ func (m *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
return m.RemoveFn(ctx, h)
|
return m.RemoveFn(ctx, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for the existence of a specific item.
|
|
||||||
func (m *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
if m.TestFn == nil {
|
|
||||||
return false, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.TestFn(ctx, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all data.
|
// Delete all data.
|
||||||
func (m *Backend) Delete(ctx context.Context) error {
|
func (m *Backend) Delete(ctx context.Context) error {
|
||||||
if m.DeleteFn == nil {
|
if m.DeleteFn == nil {
|
||||||
|
|
|
@ -308,16 +308,6 @@ func (b *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, e
|
||||||
return bi, nil
|
return bi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (b *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
_, err := b.Stat(ctx, h)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (b *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
func (b *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
if err := h.Valid(); err != nil {
|
if err := h.Valid(); err != nil {
|
||||||
|
|
|
@ -151,17 +151,6 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) (err error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test a boolean value whether a File with the name and type exists.
|
|
||||||
func (be *Backend) Test(ctx context.Context, h restic.Handle) (exists bool, err error) {
|
|
||||||
err = be.retry(ctx, fmt.Sprintf("Test(%v)", h), func() error {
|
|
||||||
var innerError error
|
|
||||||
exists, innerError = be.Backend.Test(ctx, h)
|
|
||||||
|
|
||||||
return innerError
|
|
||||||
})
|
|
||||||
return exists, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List runs fn for each file in the backend which has the type t. When an
|
// List runs fn for each file in the backend which has the type t. When an
|
||||||
// error is returned by the underlying backend, the request is retried. When fn
|
// error is returned by the underlying backend, the request is retried. When fn
|
||||||
// returns an error, the operation is aborted and the error is returned to the
|
// returns an error, the operation is aborted and the error is returned to the
|
||||||
|
|
|
@ -289,9 +289,7 @@ func TestBackendCanceledContext(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
_, err := retryBackend.Test(ctx, h)
|
_, err := retryBackend.Stat(ctx, h)
|
||||||
assertIsCanceled(t, err)
|
|
||||||
_, err = retryBackend.Stat(ctx, h)
|
|
||||||
assertIsCanceled(t, err)
|
assertIsCanceled(t, err)
|
||||||
|
|
||||||
err = retryBackend.Save(ctx, h, restic.NewByteReader([]byte{}, nil))
|
err = retryBackend.Save(ctx, h, restic.NewByteReader([]byte{}, nil))
|
||||||
|
|
|
@ -392,23 +392,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
|
||||||
return restic.FileInfo{Size: fi.Size, Name: h.Name}, nil
|
return restic.FileInfo{Size: fi.Size, Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (be *Backend) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
found := false
|
|
||||||
objName := be.Filename(h)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
_, err := be.client.StatObject(ctx, be.cfg.Bucket, objName, minio.StatObjectOptions{})
|
|
||||||
be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If error, then not found
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
|
|
@ -155,12 +155,12 @@ func newMinioTestSuite(ctx context.Context, t testing.TB) *test.Suite {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := be.Test(ctx, restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,12 +254,12 @@ func newS3TestSuite(t testing.TB) *test.Suite {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := be.Test(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -495,28 +495,6 @@ func (r *SFTP) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, erro
|
||||||
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
return restic.FileInfo{Size: fi.Size(), Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (r *SFTP) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
debug.Log("Test(%v)", h)
|
|
||||||
if err := r.clientError(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.sem.GetToken()
|
|
||||||
defer r.sem.ReleaseToken()
|
|
||||||
|
|
||||||
_, err := r.c.Lstat(r.Filename(h))
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, errors.Wrap(err, "Lstat")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the content stored at name.
|
// Remove removes the content stored at name.
|
||||||
func (r *SFTP) Remove(ctx context.Context, h restic.Handle) error {
|
func (r *SFTP) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
debug.Log("Remove(%v)", h)
|
debug.Log("Remove(%v)", h)
|
||||||
|
|
|
@ -226,25 +226,6 @@ func (be *beSwift) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
|
||||||
return restic.FileInfo{Size: obj.Bytes, Name: h.Name}, nil
|
return restic.FileInfo{Size: obj.Bytes, Name: h.Name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test returns true if a blob of the given type and name exists in the backend.
|
|
||||||
func (be *beSwift) Test(ctx context.Context, h restic.Handle) (bool, error) {
|
|
||||||
objName := be.Filename(h)
|
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
defer be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
switch _, _, err := be.conn.Object(ctx, be.container, objName); err {
|
|
||||||
case nil:
|
|
||||||
return true, nil
|
|
||||||
|
|
||||||
case swift.ObjectNotFound:
|
|
||||||
return false, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false, errors.Wrap(err, "conn.Object")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove removes the blob with the given name and type.
|
// Remove removes the blob with the given name and type.
|
||||||
func (be *beSwift) Remove(ctx context.Context, h restic.Handle) error {
|
func (be *beSwift) Remove(ctx context.Context, h restic.Handle) error {
|
||||||
objName := be.Filename(h)
|
objName := be.Filename(h)
|
||||||
|
|
|
@ -66,12 +66,12 @@ func newSwiftTestSuite(t testing.TB) *test.Suite {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := be.Test(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !be.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if err == nil {
|
||||||
return nil, errors.New("config already exists")
|
return nil, errors.New("config already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,15 @@ func seedRand(t testing.TB) {
|
||||||
t.Logf("rand initialized with seed %d", seed)
|
t.Logf("rand initialized with seed %d", seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func beTest(ctx context.Context, be restic.Backend, h restic.Handle) (bool, error) {
|
||||||
|
_, err := be.Stat(ctx, h)
|
||||||
|
if err != nil && be.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err == nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// TestCreateWithConfig tests that creating a backend in a location which already
|
// TestCreateWithConfig tests that creating a backend in a location which already
|
||||||
// has a config file fails.
|
// has a config file fails.
|
||||||
func (s *Suite) TestCreateWithConfig(t *testing.T) {
|
func (s *Suite) TestCreateWithConfig(t *testing.T) {
|
||||||
|
@ -35,7 +44,7 @@ func (s *Suite) TestCreateWithConfig(t *testing.T) {
|
||||||
|
|
||||||
// remove a config if present
|
// remove a config if present
|
||||||
cfgHandle := restic.Handle{Type: restic.ConfigFile}
|
cfgHandle := restic.Handle{Type: restic.ConfigFile}
|
||||||
cfgPresent, err := b.Test(context.TODO(), cfgHandle)
|
cfgPresent, err := beTest(context.TODO(), b, cfgHandle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to test for config: %+v", err)
|
t.Fatalf("unable to test for config: %+v", err)
|
||||||
}
|
}
|
||||||
|
@ -642,7 +651,7 @@ func (s *Suite) TestSaveWrongHash(t *testing.T) {
|
||||||
// test that upload with hash mismatch fails
|
// test that upload with hash mismatch fails
|
||||||
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
|
||||||
err := b.Save(context.TODO(), h, &wrongByteReader{ByteReader: *restic.NewByteReader(data, b.Hasher())})
|
err := b.Save(context.TODO(), h, &wrongByteReader{ByteReader: *restic.NewByteReader(data, b.Hasher())})
|
||||||
exists, err2 := b.Test(context.TODO(), h)
|
exists, err2 := beTest(context.TODO(), b, h)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatal(err2)
|
t.Fatal(err2)
|
||||||
}
|
}
|
||||||
|
@ -702,7 +711,7 @@ func (s *Suite) delayedRemove(t testing.TB, be restic.Backend, handles ...restic
|
||||||
var found bool
|
var found bool
|
||||||
var err error
|
var err error
|
||||||
for time.Since(start) <= s.WaitForDelayedRemoval {
|
for time.Since(start) <= s.WaitForDelayedRemoval {
|
||||||
found, err = be.Test(context.TODO(), h)
|
found, err = beTest(context.TODO(), be, h)
|
||||||
if s.ErrorHandler != nil {
|
if s.ErrorHandler != nil {
|
||||||
err = s.ErrorHandler(t, be, err)
|
err = s.ErrorHandler(t, be, err)
|
||||||
}
|
}
|
||||||
|
@ -764,7 +773,7 @@ func (s *Suite) TestBackend(t *testing.T) {
|
||||||
|
|
||||||
// test if blob is already in repository
|
// test if blob is already in repository
|
||||||
h := restic.Handle{Type: tpe, Name: id.String()}
|
h := restic.Handle{Type: tpe, Name: id.String()}
|
||||||
ret, err := b.Test(context.TODO(), h)
|
ret, err := beTest(context.TODO(), b, h)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
test.Assert(t, !ret, "blob was found to exist before creating")
|
test.Assert(t, !ret, "blob was found to exist before creating")
|
||||||
|
|
||||||
|
@ -777,7 +786,7 @@ func (s *Suite) TestBackend(t *testing.T) {
|
||||||
test.Assert(t, err != nil, "blob could be read before creation")
|
test.Assert(t, err != nil, "blob could be read before creation")
|
||||||
|
|
||||||
// try to get string out, should fail
|
// try to get string out, should fail
|
||||||
ret, err = b.Test(context.TODO(), h)
|
ret, err = beTest(context.TODO(), b, h)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
test.Assert(t, !ret, "id %q was found (but should not have)", ts.id)
|
test.Assert(t, !ret, "id %q was found (but should not have)", ts.id)
|
||||||
}
|
}
|
||||||
|
@ -818,7 +827,7 @@ func (s *Suite) TestBackend(t *testing.T) {
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
|
|
||||||
// test that the blob is gone
|
// test that the blob is gone
|
||||||
ok, err := b.Test(context.TODO(), h)
|
ok, err := beTest(context.TODO(), b, h)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
test.Assert(t, !ok, "removed blob still present")
|
test.Assert(t, !ok, "removed blob still present")
|
||||||
|
|
||||||
|
@ -854,9 +863,9 @@ func (s *Suite) TestBackend(t *testing.T) {
|
||||||
|
|
||||||
h := restic.Handle{Type: tpe, Name: id.String()}
|
h := restic.Handle{Type: tpe, Name: id.String()}
|
||||||
|
|
||||||
found, err := b.Test(context.TODO(), h)
|
found, err := beTest(context.TODO(), b, h)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
test.Assert(t, found, fmt.Sprintf("id %q not found", id))
|
test.Assert(t, found, fmt.Sprintf("id %v/%q not found", tpe, id))
|
||||||
|
|
||||||
handles = append(handles, h)
|
handles = append(handles, h)
|
||||||
}
|
}
|
||||||
|
|
|
@ -738,11 +738,11 @@ func (r *Repository) Init(ctx context.Context, version uint, password string, ch
|
||||||
return fmt.Errorf("repository version %v too low", version)
|
return fmt.Errorf("repository version %v too low", version)
|
||||||
}
|
}
|
||||||
|
|
||||||
has, err := r.be.Test(ctx, restic.Handle{Type: restic.ConfigFile})
|
_, err := r.be.Stat(ctx, restic.Handle{Type: restic.ConfigFile})
|
||||||
if err != nil {
|
if err != nil && !r.be.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if has {
|
if err == nil {
|
||||||
return errors.New("repository master key and config already initialized")
|
return errors.New("repository master key and config already initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,6 @@ type Backend interface {
|
||||||
// HasAtomicReplace returns whether Save() can atomically replace files
|
// HasAtomicReplace returns whether Save() can atomically replace files
|
||||||
HasAtomicReplace() bool
|
HasAtomicReplace() bool
|
||||||
|
|
||||||
// Test a boolean value whether a File with the name and type exists.
|
|
||||||
Test(ctx context.Context, h Handle) (bool, error)
|
|
||||||
|
|
||||||
// Remove removes a File described by h.
|
// Remove removes a File described by h.
|
||||||
Remove(ctx context.Context, h Handle) error
|
Remove(ctx context.Context, h Handle) error
|
||||||
|
|
||||||
|
|
|
@ -193,10 +193,11 @@ func TestLockStale(t *testing.T) {
|
||||||
|
|
||||||
func lockExists(repo restic.Repository, t testing.TB, id restic.ID) bool {
|
func lockExists(repo restic.Repository, t testing.TB, id restic.ID) bool {
|
||||||
h := restic.Handle{Type: restic.LockFile, Name: id.String()}
|
h := restic.Handle{Type: restic.LockFile, Name: id.String()}
|
||||||
exists, err := repo.Backend().Test(context.TODO(), h)
|
_, err := repo.Backend().Stat(context.TODO(), h)
|
||||||
rtest.OK(t, err)
|
if err != nil && !repo.Backend().IsNotExist(err) {
|
||||||
|
t.Fatal(err)
|
||||||
return exists
|
}
|
||||||
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLockWithStaleLock(t *testing.T) {
|
func TestLockWithStaleLock(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue