diff --git a/backend/combine/combine.go b/backend/combine/combine.go index 3fdceb128..c00f2314e 100644 --- a/backend/combine/combine.go +++ b/backend/combine/combine.go @@ -813,7 +813,7 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e if f.root == "" && dir == "" { entries = make(fs.DirEntries, 0, len(f.upstreams)) for combineDir := range f.upstreams { - d := fs.NewDir(combineDir, f.when) + d := fs.NewLimitedDirWrapper(combineDir, fs.NewDir(combineDir, f.when)) entries = append(entries, d) } return entries, nil @@ -1002,7 +1002,7 @@ func (f *Fs) DirSetModTime(ctx context.Context, dir string, modTime time.Time) e return err } if uDir == "" { - fs.Debugf(dir, "can't set modtime on upstream root. skipping.") + fs.Debugf(dir, "Can't set modtime on upstream root. skipping.") return nil } if do := u.f.Features().DirSetModTime; do != nil { diff --git a/fs/dir_wrapper.go b/fs/dir_wrapper.go index 9fe135703..1560961e2 100644 --- a/fs/dir_wrapper.go +++ b/fs/dir_wrapper.go @@ -7,8 +7,9 @@ import ( // DirWrapper wraps a Directory object so the Remote can be overridden type DirWrapper struct { - Directory // Directory we are wrapping - remote string // name of the directory + Directory // Directory we are wrapping + remote string // name of the directory + failSilently bool // if set, ErrorNotImplemented should not be considered an error for this directory } // NewDirWrapper creates a wrapper for a directory object @@ -22,6 +23,16 @@ func NewDirWrapper(remote string, d Directory) *DirWrapper { } } +// NewLimitedDirWrapper creates a DirWrapper that should fail silently instead of erroring for ErrorNotImplemented. +// +// Intended for exceptional dirs lacking abilities that the Fs otherwise usually supports +// (ex. a Combine root which can't set metadata/modtime, regardless of support by wrapped backend) +func NewLimitedDirWrapper(remote string, d Directory) *DirWrapper { + dw := NewDirWrapper(remote, d) + dw.failSilently = true + return dw +} + // String returns the name func (d *DirWrapper) String() string { return d.remote @@ -55,6 +66,10 @@ func (d *DirWrapper) Metadata(ctx context.Context) (Metadata, error) { func (d *DirWrapper) SetMetadata(ctx context.Context, metadata Metadata) error { do, ok := d.Directory.(SetMetadataer) if !ok { + if d.failSilently { + Debugf(d, "Can't SetMetadata for this directory (%T from %v) -- skipping", d.Directory, d.Fs()) + return nil + } return ErrorNotImplemented } return do.SetMetadata(ctx, metadata) @@ -66,6 +81,10 @@ func (d *DirWrapper) SetMetadata(ctx context.Context, metadata Metadata) error { func (d *DirWrapper) SetModTime(ctx context.Context, t time.Time) error { do, ok := d.Directory.(SetModTimer) if !ok { + if d.failSilently { + Debugf(d, "Can't SetModTime for this directory (%T from %v) -- skipping", d.Directory, d.Fs()) + return nil + } return ErrorNotImplemented } return do.SetModTime(ctx, t)