combine: implement missing methods
Implement these missing methods: - PublicLink - PutUnchecked - MergeDirs - CleanUp - OpenWriterAt And declare these ones unimplementable: - UnWrap - WrapFs - SetWrapper - UserInfo - Disconnect Fixes #6999
This commit is contained in:
parent
09a408664d
commit
487e4f09b3
2 changed files with 124 additions and 4 deletions
|
@ -289,6 +289,16 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (outFs fs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable CleanUp when any upstreams support it
|
||||||
|
if features.CleanUp == nil {
|
||||||
|
for _, u := range f.upstreams {
|
||||||
|
if u.f.Features().CleanUp != nil {
|
||||||
|
features.CleanUp = f.CleanUp
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Enable ChangeNotify when any upstreams support it
|
// Enable ChangeNotify when any upstreams support it
|
||||||
if features.ChangeNotify == nil {
|
if features.ChangeNotify == nil {
|
||||||
for _, u := range f.upstreams {
|
for _, u := range f.upstreams {
|
||||||
|
@ -890,6 +900,100 @@ func (f *Fs) Shutdown(ctx context.Context) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PublicLink generates a public link to the remote path (usually readable by anyone)
|
||||||
|
func (f *Fs) PublicLink(ctx context.Context, remote string, expire fs.Duration, unlink bool) (string, error) {
|
||||||
|
u, uRemote, err := f.findUpstream(remote)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
do := u.f.Features().PublicLink
|
||||||
|
if do == nil {
|
||||||
|
return "", fs.ErrorNotImplemented
|
||||||
|
}
|
||||||
|
return do(ctx, uRemote, expire, unlink)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put in to the remote path with the modTime given of the given size
|
||||||
|
//
|
||||||
|
// May create the object even if it returns an error - if so
|
||||||
|
// will return the object and the error, otherwise will return
|
||||||
|
// nil and the error
|
||||||
|
//
|
||||||
|
// May create duplicates or return errors if src already
|
||||||
|
// exists.
|
||||||
|
func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
|
||||||
|
srcPath := src.Remote()
|
||||||
|
u, uRemote, err := f.findUpstream(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
do := u.f.Features().PutUnchecked
|
||||||
|
if do == nil {
|
||||||
|
return nil, fs.ErrorNotImplemented
|
||||||
|
}
|
||||||
|
uSrc := fs.NewOverrideRemote(src, uRemote)
|
||||||
|
return do(ctx, in, uSrc, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeDirs merges the contents of all the directories passed
|
||||||
|
// in into the first one and rmdirs the other directories.
|
||||||
|
func (f *Fs) MergeDirs(ctx context.Context, dirs []fs.Directory) error {
|
||||||
|
if len(dirs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
u *upstream
|
||||||
|
uDirs []fs.Directory
|
||||||
|
)
|
||||||
|
for _, dir := range dirs {
|
||||||
|
uNew, uDir, err := f.findUpstream(dir.Remote())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if u == nil {
|
||||||
|
u = uNew
|
||||||
|
} else if u != uNew {
|
||||||
|
return fmt.Errorf("can't merge dirctories from different upstreams")
|
||||||
|
}
|
||||||
|
uDirs = append(uDirs, fs.NewOverrideDirectory(dir, uDir))
|
||||||
|
}
|
||||||
|
do := u.f.Features().MergeDirs
|
||||||
|
if do == nil {
|
||||||
|
return fs.ErrorNotImplemented
|
||||||
|
}
|
||||||
|
return do(ctx, uDirs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanUp the trash in the Fs
|
||||||
|
//
|
||||||
|
// Implement this if you have a way of emptying the trash or
|
||||||
|
// otherwise cleaning up old versions of files.
|
||||||
|
func (f *Fs) CleanUp(ctx context.Context) error {
|
||||||
|
return f.multithread(ctx, func(ctx context.Context, u *upstream) error {
|
||||||
|
if do := u.f.Features().CleanUp; do != nil {
|
||||||
|
return do(ctx)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenWriterAt opens with a handle for random access writes
|
||||||
|
//
|
||||||
|
// Pass in the remote desired and the size if known.
|
||||||
|
//
|
||||||
|
// It truncates any existing object
|
||||||
|
func (f *Fs) OpenWriterAt(ctx context.Context, remote string, size int64) (fs.WriterAtCloser, error) {
|
||||||
|
u, uRemote, err := f.findUpstream(remote)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
do := u.f.Features().OpenWriterAt
|
||||||
|
if do == nil {
|
||||||
|
return nil, fs.ErrorNotImplemented
|
||||||
|
}
|
||||||
|
return do(ctx, uRemote, size)
|
||||||
|
}
|
||||||
|
|
||||||
// Object describes a wrapped Object
|
// Object describes a wrapped Object
|
||||||
//
|
//
|
||||||
// This is a wrapped Object which knows its path prefix
|
// This is a wrapped Object which knows its path prefix
|
||||||
|
@ -991,5 +1095,10 @@ var (
|
||||||
_ fs.Abouter = (*Fs)(nil)
|
_ fs.Abouter = (*Fs)(nil)
|
||||||
_ fs.ListRer = (*Fs)(nil)
|
_ fs.ListRer = (*Fs)(nil)
|
||||||
_ fs.Shutdowner = (*Fs)(nil)
|
_ fs.Shutdowner = (*Fs)(nil)
|
||||||
|
_ fs.PublicLinker = (*Fs)(nil)
|
||||||
|
_ fs.PutUncheckeder = (*Fs)(nil)
|
||||||
|
_ fs.MergeDirser = (*Fs)(nil)
|
||||||
|
_ fs.CleanUpper = (*Fs)(nil)
|
||||||
|
_ fs.OpenWriterAter = (*Fs)(nil)
|
||||||
_ fs.FullObject = (*Object)(nil)
|
_ fs.FullObject = (*Object)(nil)
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,11 @@ import (
|
||||||
"github.com/rclone/rclone/fstest/fstests"
|
"github.com/rclone/rclone/fstest/fstests"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
unimplementableFsMethods = []string{"UnWrap", "WrapFs", "SetWrapper", "UserInfo", "Disconnect"}
|
||||||
|
unimplementableObjectMethods = []string{}
|
||||||
|
)
|
||||||
|
|
||||||
// TestIntegration runs integration tests against the remote
|
// TestIntegration runs integration tests against the remote
|
||||||
func TestIntegration(t *testing.T) {
|
func TestIntegration(t *testing.T) {
|
||||||
if *fstest.RemoteName == "" {
|
if *fstest.RemoteName == "" {
|
||||||
|
@ -17,8 +22,8 @@ func TestIntegration(t *testing.T) {
|
||||||
}
|
}
|
||||||
fstests.Run(t, &fstests.Opt{
|
fstests.Run(t, &fstests.Opt{
|
||||||
RemoteName: *fstest.RemoteName,
|
RemoteName: *fstest.RemoteName,
|
||||||
UnimplementableFsMethods: []string{"OpenWriterAt", "DuplicateFiles"},
|
UnimplementableFsMethods: unimplementableFsMethods,
|
||||||
UnimplementableObjectMethods: []string{"MimeType"},
|
UnimplementableObjectMethods: unimplementableObjectMethods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +40,9 @@ func TestLocal(t *testing.T) {
|
||||||
{Name: name, Key: "type", Value: "combine"},
|
{Name: name, Key: "type", Value: "combine"},
|
||||||
{Name: name, Key: "upstreams", Value: upstreams},
|
{Name: name, Key: "upstreams", Value: upstreams},
|
||||||
},
|
},
|
||||||
QuickTestOK: true,
|
QuickTestOK: true,
|
||||||
|
UnimplementableFsMethods: unimplementableFsMethods,
|
||||||
|
UnimplementableObjectMethods: unimplementableObjectMethods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +58,9 @@ func TestMemory(t *testing.T) {
|
||||||
{Name: name, Key: "type", Value: "combine"},
|
{Name: name, Key: "type", Value: "combine"},
|
||||||
{Name: name, Key: "upstreams", Value: upstreams},
|
{Name: name, Key: "upstreams", Value: upstreams},
|
||||||
},
|
},
|
||||||
QuickTestOK: true,
|
QuickTestOK: true,
|
||||||
|
UnimplementableFsMethods: unimplementableFsMethods,
|
||||||
|
UnimplementableObjectMethods: unimplementableObjectMethods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +77,8 @@ func TestMixed(t *testing.T) {
|
||||||
{Name: name, Key: "type", Value: "combine"},
|
{Name: name, Key: "type", Value: "combine"},
|
||||||
{Name: name, Key: "upstreams", Value: upstreams},
|
{Name: name, Key: "upstreams", Value: upstreams},
|
||||||
},
|
},
|
||||||
|
UnimplementableFsMethods: unimplementableFsMethods,
|
||||||
|
UnimplementableObjectMethods: unimplementableObjectMethods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue