backend: extract most debug logs into logger backend

This commit is contained in:
Michael Eischer 2023-04-07 22:01:30 +02:00
parent 8bfc2519d7
commit 4703473ec5
12 changed files with 99 additions and 100 deletions

View file

@ -20,6 +20,7 @@ import (
"github.com/restic/restic/internal/backend/limiter"
"github.com/restic/restic/internal/backend/local"
"github.com/restic/restic/internal/backend/location"
"github.com/restic/restic/internal/backend/logger"
"github.com/restic/restic/internal/backend/rclone"
"github.com/restic/restic/internal/backend/rest"
"github.com/restic/restic/internal/backend/retry"
@ -743,6 +744,9 @@ func open(ctx context.Context, s string, gopts GlobalOptions, opts options.Optio
return nil, errors.Fatalf("unable to open repository at %v: %v", location.StripPassword(s), err)
}
// wrap with debug logging
be = logger.New(be)
// wrap backend if a test specified an inner hook
if gopts.backendInnerTestHook != nil {
be, err = gopts.backendInnerTestHook(be)
@ -787,27 +791,34 @@ func create(ctx context.Context, s string, opts options.Options) (restic.Backend
return nil, err
}
var be restic.Backend
switch loc.Scheme {
case "local":
return local.Create(ctx, cfg.(local.Config))
be, err = local.Create(ctx, cfg.(local.Config))
case "sftp":
return sftp.Create(ctx, cfg.(sftp.Config))
be, err = sftp.Create(ctx, cfg.(sftp.Config))
case "s3":
return s3.Create(ctx, cfg.(s3.Config), rt)
be, err = s3.Create(ctx, cfg.(s3.Config), rt)
case "gs":
return gs.Create(cfg.(gs.Config), rt)
be, err = gs.Create(cfg.(gs.Config), rt)
case "azure":
return azure.Create(ctx, cfg.(azure.Config), rt)
be, err = azure.Create(ctx, cfg.(azure.Config), rt)
case "swift":
return swift.Open(ctx, cfg.(swift.Config), rt)
be, err = swift.Open(ctx, cfg.(swift.Config), rt)
case "b2":
return b2.Create(ctx, cfg.(b2.Config), rt)
be, err = b2.Create(ctx, cfg.(b2.Config), rt)
case "rest":
return rest.Create(ctx, cfg.(rest.Config), rt)
be, err = rest.Create(ctx, cfg.(rest.Config), rt)
case "rclone":
return rclone.Create(ctx, cfg.(rclone.Config))
be, err = rclone.Create(ctx, cfg.(rclone.Config))
default:
debug.Log("invalid repository scheme: %v", s)
return nil, errors.Fatalf("invalid scheme %q", loc.Scheme)
}
debug.Log("invalid repository scheme: %v", s)
return nil, errors.Fatalf("invalid scheme %q", loc.Scheme)
if err != nil {
return nil, err
}
return logger.New(be), nil
}

View file

@ -152,7 +152,6 @@ func (be *Backend) SetListMaxItems(i int) {
// IsNotExist returns true if the error is caused by a not existing file.
func (be *Backend) IsNotExist(err error) bool {
debug.Log("IsNotExist(%T, %#v)", err, err)
return bloberror.HasCode(err, bloberror.BlobNotFound)
}
@ -193,8 +192,6 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
objName := be.Filename(h)
debug.Log("Save %v at %v", h, objName)
be.sem.GetToken()
debug.Log("InsertObject(%v, %v)", be.cfg.AccountName, objName)
@ -209,8 +206,6 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
}
be.sem.ReleaseToken()
debug.Log("%v, err %#v", objName, err)
return err
}
@ -299,8 +294,6 @@ func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
}
func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v from %v", h, length, offset, be.Filename(h))
objName := be.Filename(h)
blockBlobClient := be.container.NewBlobClient(objName)
@ -322,8 +315,6 @@ func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int,
// Stat returns information about a blob.
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
debug.Log("%v", h)
objName := be.Filename(h)
blobClient := be.container.NewBlobClient(objName)
@ -332,7 +323,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo,
be.sem.ReleaseToken()
if err != nil {
debug.Log("blob.GetProperties err %v", err)
return restic.FileInfo{}, errors.Wrap(err, "blob.GetProperties")
}
@ -352,8 +342,6 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
_, err := blob.Delete(ctx, &azblob.DeleteBlobOptions{})
be.sem.ReleaseToken()
debug.Log("Remove(%v) at %v -> err %v", h, objName, err)
if be.IsNotExist(err) {
return nil
}
@ -364,8 +352,6 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (be *Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("listing %v", t)
prefix, _ := be.Basedir(t)
// make sure prefix ends with a slash

View file

@ -206,8 +206,6 @@ func (be *b2Backend) Load(ctx context.Context, h restic.Handle, length int, offs
}
func (be *b2Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v from %v", h, length, offset, be.Filename(h))
ctx, cancel := context.WithCancel(ctx)
be.sem.GetToken()
@ -249,7 +247,6 @@ func (be *b2Backend) Save(ctx context.Context, h restic.Handle, rd restic.Rewind
// b2 always requires sha1 checksums for uploaded file parts
w := obj.NewWriter(ctx)
n, err := io.Copy(w, rd)
debug.Log(" saved %d bytes, err %v", n, err)
if err != nil {
_ = w.Close()
@ -265,8 +262,6 @@ func (be *b2Backend) Save(ctx context.Context, h restic.Handle, rd restic.Rewind
// Stat returns information about a blob.
func (be *b2Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInfo, err error) {
debug.Log("Stat %v", h)
be.sem.GetToken()
defer be.sem.ReleaseToken()
@ -274,7 +269,6 @@ func (be *b2Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileI
obj := be.bucket.Object(name)
info, err := obj.Attrs(ctx)
if err != nil {
debug.Log("Attrs() err %v", err)
return restic.FileInfo{}, errors.Wrap(err, "Stat")
}
return restic.FileInfo{Size: info.Size, Name: h.Name}, nil
@ -282,8 +276,6 @@ func (be *b2Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileI
// Remove removes the blob with the given name and type.
func (be *b2Backend) Remove(ctx context.Context, h restic.Handle) error {
debug.Log("Remove %v", h)
be.sem.GetToken()
defer be.sem.ReleaseToken()
@ -330,8 +322,6 @@ func (sm *semLocker) Unlock() { sm.ReleaseToken() }
// List returns a channel that yields all names of blobs of type t.
func (be *b2Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("List %v", t)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@ -356,7 +346,6 @@ func (be *b2Backend) List(ctx context.Context, t restic.FileType, fn func(restic
}
}
if err := iter.Err(); err != nil {
debug.Log("List: %v", err)
return err
}
return nil
@ -364,7 +353,6 @@ func (be *b2Backend) List(ctx context.Context, t restic.FileType, fn func(restic
// Remove keys for a specified backend type.
func (be *b2Backend) removeKeys(ctx context.Context, t restic.FileType) error {
debug.Log("removeKeys %v", t)
return be.List(ctx, t, func(fi restic.FileInfo) error {
return be.Remove(ctx, restic.Handle{Type: t, Name: fi.Name})
})

View file

@ -34,8 +34,6 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
return err
}
debug.Log("faked saving %v bytes at %v", rd.Length(), h)
// don't save anything, just return ok
return nil
}

View file

@ -169,7 +169,6 @@ func (be *Backend) SetListMaxItems(i int) {
// IsNotExist returns true if the error is caused by a not existing file.
func (be *Backend) IsNotExist(err error) bool {
debug.Log("IsNotExist(%T, %#v)", err, err)
return errors.Is(err, storage.ErrObjectNotExist)
}
@ -210,8 +209,6 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
objName := be.Filename(h)
debug.Log("Save %v at %v", h, objName)
be.sem.GetToken()
debug.Log("InsertObject(%v, %v)", be.bucketName, objName)
@ -253,11 +250,9 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
be.sem.ReleaseToken()
if err != nil {
debug.Log("%v: err %#v: %v", objName, err, err)
return errors.Wrap(err, "service.Objects.Insert")
}
debug.Log("%v -> %v bytes", objName, wbytes)
// sanity check
if wbytes != rd.Length() {
return errors.Errorf("wrote %d bytes instead of the expected %d bytes", wbytes, rd.Length())
@ -272,8 +267,6 @@ func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
}
func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v from %v", h, length, offset, be.Filename(h))
if length == 0 {
// negative length indicates read till end to GCS lib
length = -1
@ -297,8 +290,6 @@ func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int,
// Stat returns information about a blob.
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInfo, err error) {
debug.Log("%v", h)
objName := be.Filename(h)
be.sem.GetToken()
@ -306,7 +297,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
be.sem.ReleaseToken()
if err != nil {
debug.Log("GetObjectAttributes() err %v", err)
return restic.FileInfo{}, errors.Wrap(err, "service.Objects.Get")
}
@ -325,15 +315,12 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
err = nil
}
debug.Log("Remove(%v) at %v -> err %v", h, objName, err)
return errors.Wrap(err, "client.RemoveObject")
}
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (be *Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("listing %v", t)
prefix, _ := be.Basedir(t)
// make sure prefix ends with a slash

View file

@ -114,7 +114,6 @@ func (b *Local) IsNotExist(err error) bool {
// Save stores data in the backend at the handle.
func (b *Local) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader) (err error) {
debug.Log("Save %v", h)
if err := h.Valid(); err != nil {
return backoff.Permanent(err)
}
@ -217,8 +216,6 @@ func (b *Local) Load(ctx context.Context, h restic.Handle, length int, offset in
}
func (b *Local) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v", h, length, offset)
b.sem.GetToken()
f, err := fs.Open(b.Filename(h))
if err != nil {
@ -246,7 +243,6 @@ func (b *Local) openReader(ctx context.Context, h restic.Handle, length int, off
// Stat returns information about a blob.
func (b *Local) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
debug.Log("Stat %v", h)
if err := h.Valid(); err != nil {
return restic.FileInfo{}, backoff.Permanent(err)
}
@ -264,7 +260,6 @@ func (b *Local) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, err
// Remove removes the blob with the given name and type.
func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
debug.Log("Remove %v", h)
fn := b.Filename(h)
b.sem.GetToken()
@ -282,8 +277,6 @@ func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (b *Local) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) (err error) {
debug.Log("List %v", t)
basedir, subdirs := b.Basedir(t)
if subdirs {
err = visitDirs(ctx, basedir, fn)
@ -377,13 +370,11 @@ func visitFiles(ctx context.Context, dir string, fn func(restic.FileInfo) error,
// Delete removes the repository and all files.
func (b *Local) Delete(ctx context.Context) error {
debug.Log("Delete()")
return fs.RemoveAll(b.Path)
}
// Close closes all open files.
func (b *Local) Close() error {
debug.Log("Close()")
// this does not need to do anything, all open files are closed within the
// same function.
return nil

View file

@ -0,0 +1,77 @@
package logger
import (
"context"
"io"
"github.com/restic/restic/internal/debug"
"github.com/restic/restic/internal/restic"
)
type Backend struct {
restic.Backend
}
// statically ensure that Backend implements restic.Backend.
var _ restic.Backend = &Backend{}
func New(be restic.Backend) *Backend {
return &Backend{Backend: be}
}
func (be *Backend) IsNotExist(err error) bool {
isNotExist := be.Backend.IsNotExist(err)
debug.Log("IsNotExist(%T, %#v, %v)", err, err, isNotExist)
return isNotExist
}
// Save adds new Data to the backend.
func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader) error {
debug.Log("Save(%v, %v)", h, rd.Length())
err := be.Backend.Save(ctx, h, rd)
debug.Log(" save err %v", err)
return err
}
// Remove deletes a file from the backend.
func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
debug.Log("Remove(%v)", h)
err := be.Backend.Remove(ctx, h)
debug.Log(" remove err %v", err)
return err
}
func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset int64, fn func(io.Reader) error) error {
debug.Log("Load(%v, length %v, offset %v)", h, length, offset)
err := be.Backend.Load(ctx, h, length, offset, fn)
debug.Log(" load err %v", err)
return err
}
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
debug.Log("Stat(%v)", h)
fi, err := be.Backend.Stat(ctx, h)
debug.Log(" stat err %v", err)
return fi, err
}
func (be *Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("List(%v)", t)
err := be.Backend.List(ctx, t, fn)
debug.Log(" list err %v", err)
return err
}
func (be *Backend) Delete(ctx context.Context) error {
debug.Log("Delete()")
err := be.Backend.Delete(ctx)
debug.Log(" delete err %v", err)
return err
}
func (be *Backend) Close() error {
debug.Log("Close()")
err := be.Backend.Close()
debug.Log(" close err %v", err)
return err
}

View file

@ -102,7 +102,6 @@ func (be *MemoryBackend) Save(ctx context.Context, h restic.Handle, rd restic.Re
}
be.data[h] = buf
debug.Log("saved %v bytes at %v", len(buf), h)
return ctx.Err()
}
@ -167,8 +166,6 @@ func (be *MemoryBackend) Stat(ctx context.Context, h restic.Handle) (restic.File
h.Name = ""
}
debug.Log("stat %v", h)
e, ok := be.data[h]
if !ok {
return restic.FileInfo{}, errNotFound

View file

@ -212,7 +212,6 @@ func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
}
func (b *Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v", h, length, offset)
if err := h.Valid(); err != nil {
return nil, backoff.Permanent(err)
}

View file

@ -169,8 +169,6 @@ func isAccessDenied(err error) bool {
// IsNotExist returns true if the error is caused by a not existing file.
func (be *Backend) IsNotExist(err error) bool {
debug.Log("IsNotExist(%T, %#v)", err, err)
var e minio.ErrorResponse
return errors.As(err, &e) && e.Code == "NoSuchKey"
}
@ -273,8 +271,6 @@ func (be *Backend) Path() string {
// Save stores data in the backend at the handle.
func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader) error {
debug.Log("Save %v", h)
if err := h.Valid(); err != nil {
return backoff.Permanent(err)
}
@ -294,8 +290,6 @@ func (be *Backend) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
debug.Log("PutObject(%v, %v, %v)", be.cfg.Bucket, objName, rd.Length())
info, err := be.client.PutObject(ctx, be.cfg.Bucket, objName, io.NopCloser(rd), int64(rd.Length()), opts)
debug.Log("%v -> %v bytes, err %#v: %v", objName, info.Size, err, err)
// sanity check
if err == nil && info.Size != rd.Length() {
return errors.Errorf("wrote %d bytes instead of the expected %d bytes", info.Size, rd.Length())
@ -311,8 +305,6 @@ func (be *Backend) Load(ctx context.Context, h restic.Handle, length int, offset
}
func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v from %v", h, length, offset, be.Filename(h))
objName := be.Filename(h)
opts := minio.GetObjectOptions{}
@ -345,8 +337,6 @@ func (be *Backend) openReader(ctx context.Context, h restic.Handle, length int,
// Stat returns information about a blob.
func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInfo, err error) {
debug.Log("%v", h)
objName := be.Filename(h)
var obj *minio.Object
@ -355,7 +345,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
be.sem.GetToken()
obj, err = be.client.GetObject(ctx, be.cfg.Bucket, objName, opts)
if err != nil {
debug.Log("GetObject() err %v", err)
be.sem.ReleaseToken()
return restic.FileInfo{}, errors.Wrap(err, "client.GetObject")
}
@ -371,7 +360,6 @@ func (be *Backend) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
fi, err := obj.Stat()
if err != nil {
debug.Log("Stat() err %v", err)
return restic.FileInfo{}, errors.Wrap(err, "Stat")
}
@ -386,8 +374,6 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
err := be.client.RemoveObject(ctx, be.cfg.Bucket, objName, minio.RemoveObjectOptions{})
be.sem.ReleaseToken()
debug.Log("Remove(%v) at %v -> err %v", h, objName, err)
if be.IsNotExist(err) {
err = nil
}
@ -398,8 +384,6 @@ func (be *Backend) Remove(ctx context.Context, h restic.Handle) error {
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (be *Backend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("listing %v", t)
prefix, recursive := be.Basedir(t)
// make sure prefix ends with a slash

View file

@ -304,7 +304,6 @@ func tempSuffix() string {
// Save stores data in the backend at the handle.
func (r *SFTP) Save(ctx context.Context, h restic.Handle, rd restic.RewindReader) error {
debug.Log("Save %v", h)
if err := r.clientError(); err != nil {
return err
}
@ -429,8 +428,6 @@ func (wr *wrapReader) Close() error {
}
func (r *SFTP) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v", h, length, offset)
r.sem.GetToken()
f, err := r.c.Open(r.Filename(h))
if err != nil {
@ -467,7 +464,6 @@ func (r *SFTP) openReader(ctx context.Context, h restic.Handle, length int, offs
// Stat returns information about a blob.
func (r *SFTP) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, error) {
debug.Log("Stat(%v)", h)
if err := r.clientError(); err != nil {
return restic.FileInfo{}, err
}
@ -489,7 +485,6 @@ func (r *SFTP) Stat(ctx context.Context, h restic.Handle) (restic.FileInfo, erro
// Remove removes the content stored at name.
func (r *SFTP) Remove(ctx context.Context, h restic.Handle) error {
debug.Log("Remove(%v)", h)
if err := r.clientError(); err != nil {
return err
}
@ -503,8 +498,6 @@ func (r *SFTP) Remove(ctx context.Context, h restic.Handle) error {
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (r *SFTP) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("List %v", t)
basedir, subdirs := r.Basedir(t)
walker := r.c.Walk(basedir)
for {
@ -565,7 +558,6 @@ var closeTimeout = 2 * time.Second
// Close closes the sftp connection and terminates the underlying command.
func (r *SFTP) Close() error {
debug.Log("Close")
if r == nil {
return nil
}

View file

@ -143,7 +143,6 @@ func (be *beSwift) Load(ctx context.Context, h restic.Handle, length int, offset
}
func (be *beSwift) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
debug.Log("Load %v, length %v, offset %v", h, length, offset)
objName := be.Filename(h)
@ -163,7 +162,6 @@ func (be *beSwift) openReader(ctx context.Context, h restic.Handle, length int,
be.sem.GetToken()
obj, _, err := be.conn.ObjectOpen(ctx, be.container, objName, false, headers)
if err != nil {
debug.Log(" err %v", err)
be.sem.ReleaseToken()
return nil, errors.Wrap(err, "conn.ObjectOpen")
}
@ -179,8 +177,6 @@ func (be *beSwift) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
objName := be.Filename(h)
debug.Log("Save %v at %v", h, objName)
be.sem.GetToken()
defer be.sem.ReleaseToken()
@ -192,15 +188,12 @@ func (be *beSwift) Save(ctx context.Context, h restic.Handle, rd restic.RewindRe
be.container, objName, rd, true, hex.EncodeToString(rd.Hash()),
encoding, hdr)
// swift does not return the upload length
debug.Log("%v, err %#v", objName, err)
return errors.Wrap(err, "client.PutObject")
}
// Stat returns information about a blob.
func (be *beSwift) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInfo, err error) {
debug.Log("%v", h)
objName := be.Filename(h)
be.sem.GetToken()
@ -208,7 +201,6 @@ func (be *beSwift) Stat(ctx context.Context, h restic.Handle) (bi restic.FileInf
obj, _, err := be.conn.Object(ctx, be.container, objName)
if err != nil {
debug.Log("Object() err %v", err)
return restic.FileInfo{}, errors.Wrap(err, "conn.Object")
}
@ -223,15 +215,12 @@ func (be *beSwift) Remove(ctx context.Context, h restic.Handle) error {
defer be.sem.ReleaseToken()
err := be.conn.ObjectDelete(ctx, be.container, objName)
debug.Log("Remove(%v) -> err %v", h, err)
return errors.Wrap(err, "conn.ObjectDelete")
}
// List runs fn for each file in the backend which has the type t. When an
// error occurs (or fn returns an error), List stops and returns it.
func (be *beSwift) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
debug.Log("listing %v", t)
prefix, _ := be.Basedir(t)
prefix += "/"