diff --git a/cache/cache.go b/cache/cache.go index 89a046d41..9d4abf7a5 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -206,6 +206,7 @@ type Storage interface { // Fs represents a wrapped fs.Fs type Fs struct { fs.Fs + wrapper fs.Fs name string root string @@ -379,7 +380,9 @@ func NewFs(name, rpath string) (fs.Fs, error) { PutStream: f.PutStream, CleanUp: f.CleanUp, UnWrap: f.UnWrap, - }).Fill(f).Mask(wrappedFs) + WrapFs: f.WrapFs, + SetWrapper: f.SetWrapper, + }).Fill(f).Mask(wrappedFs).WrapsFs(f, wrappedFs) return f, wrapErr } @@ -938,6 +941,16 @@ func (f *Fs) UnWrap() fs.Fs { return f.Fs } +// WrapFs returns the Fs that is wrapping this Fs +func (f *Fs) WrapFs() fs.Fs { + return f.wrapper +} + +// SetWrapper sets the Fs that is wrapping this Fs +func (f *Fs) SetWrapper(wrapper fs.Fs) { + f.wrapper = wrapper +} + // DirCacheFlush flushes the dir cache func (f *Fs) DirCacheFlush() { _ = f.cache.RemoveDir("") @@ -963,5 +976,6 @@ var ( _ fs.PutStreamer = (*Fs)(nil) _ fs.CleanUpper = (*Fs)(nil) _ fs.UnWrapper = (*Fs)(nil) + _ fs.Wrapper = (*Fs)(nil) _ fs.ListRer = (*Fs)(nil) ) diff --git a/crypt/crypt.go b/crypt/crypt.go index ea725b702..87a3a4694 100644 --- a/crypt/crypt.go +++ b/crypt/crypt.go @@ -129,7 +129,7 @@ func NewFs(name, rpath string) (fs.Fs, error) { WriteMimeType: false, BucketBased: true, CanHaveEmptyDirectories: true, - }).Fill(f).Mask(wrappedFs) + }).Fill(f).Mask(wrappedFs).WrapsFs(f, wrappedFs) doDirChangeNotify := wrappedFs.Features().DirChangeNotify if doDirChangeNotify != nil { diff --git a/fs/fs.go b/fs/fs.go index a96bff041..dc8a43751 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -301,6 +301,12 @@ type Features struct { // UnWrap returns the Fs that this Fs is wrapping UnWrap func() Fs + // WrapFs returns the Fs that is wrapping this Fs + WrapFs func() Fs + + // SetWrapper sets the Fs that is wrapping this Fs + SetWrapper func(f Fs) + // DirCacheFlush resets the directory cache - used in testing // as an optional interface DirCacheFlush func() @@ -413,6 +419,10 @@ func (ft *Features) Fill(f Fs) *Features { if do, ok := f.(UnWrapper); ok { ft.UnWrap = do.UnWrap } + if do, ok := f.(Wrapper); ok { + ft.WrapFs = do.WrapFs + ft.SetWrapper = do.SetWrapper + } if do, ok := f.(DirCacheFlusher); ok { ft.DirCacheFlush = do.DirCacheFlush } @@ -438,7 +448,7 @@ func (ft *Features) Fill(f Fs) *Features { // // Only optional features which are implemented in both the original // Fs AND the one passed in will be advertised. Any features which -// aren't in both will be set to false/nil, except for UnWrap which +// aren't in both will be set to false/nil, except for UnWrap/Wrap which // will be left untouched. func (ft *Features) Mask(f Fs) *Features { mask := f.Features() @@ -487,7 +497,7 @@ func (ft *Features) Mask(f Fs) *Features { return ft.DisableList(Config.DisableFeatures) } -// Wrap makes a Copy of the features passed in, overriding the UnWrap +// Wrap makes a Copy of the features passed in, overriding the UnWrap/Wrap // method only if available in f. func (ft *Features) Wrap(f Fs) *Features { copy := new(Features) @@ -495,9 +505,22 @@ func (ft *Features) Wrap(f Fs) *Features { if do, ok := f.(UnWrapper); ok { copy.UnWrap = do.UnWrap } + if do, ok := f.(Wrapper); ok { + copy.WrapFs = do.WrapFs + copy.SetWrapper = do.SetWrapper + } return copy } +// WrapsFs adds extra information between `f` which wraps `w` +func (ft *Features) WrapsFs(f Fs, w Fs) *Features { + wFeatures := w.Features() + if wFeatures.WrapFs != nil && wFeatures.SetWrapper != nil { + wFeatures.SetWrapper(f) + } + return ft +} + // Purger is an optional interfaces for Fs type Purger interface { // Purge all files in the root and the root directory @@ -564,6 +587,14 @@ type UnWrapper interface { UnWrap() Fs } +// Wrapper is an optional interfaces for Fs +type Wrapper interface { + // Wrap returns the Fs that is wrapping this Fs + WrapFs() Fs + // SetWrapper sets the Fs that is wrapping this Fs + SetWrapper(f Fs) +} + // DirCacheFlusher is an optional interface for Fs type DirCacheFlusher interface { // DirCacheFlush resets the directory cache - used in testing