rc: Add GetFsNamedFileOK to get an fs which could also be a file
This commit is contained in:
parent
5994fcfed8
commit
0b8689dc28
2 changed files with 92 additions and 6 deletions
|
@ -5,27 +5,71 @@ package rc
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
"github.com/rclone/rclone/fs/cache"
|
||||
"github.com/rclone/rclone/fs/config/configmap"
|
||||
"github.com/rclone/rclone/fs/filter"
|
||||
"github.com/rclone/rclone/fs/fspath"
|
||||
)
|
||||
|
||||
// GetFsNamed gets an fs.Fs named fsName either from the cache or creates it afresh
|
||||
func GetFsNamed(ctx context.Context, in Params, fsName string) (f fs.Fs, err error) {
|
||||
fsString, err := in.GetString(fsName)
|
||||
// getFsName gets an fs name from fsName either from the cache or direct
|
||||
func getFsName(in Params, fsName string) (fsString string, err error) {
|
||||
fsString, err = in.GetString(fsName)
|
||||
if err != nil {
|
||||
if !IsErrParamInvalid(err) {
|
||||
return nil, err
|
||||
return fsString, err
|
||||
}
|
||||
fsString, err = getConfigMap(in, fsName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return fsString, err
|
||||
}
|
||||
}
|
||||
return fsString, err
|
||||
}
|
||||
|
||||
// GetFsNamed gets an fs.Fs named fsName either from the cache or creates it afresh
|
||||
func GetFsNamed(ctx context.Context, in Params, fsName string) (f fs.Fs, err error) {
|
||||
fsString, err := getFsName(in, fsName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cache.Get(ctx, fsString)
|
||||
}
|
||||
|
||||
// GetFsNamedFileOK gets an fs.Fs named fsName either from the cache or creates it afresh
|
||||
//
|
||||
// If the fs.Fs points to a single file then it returns a new ctx with
|
||||
// filters applied to make the listings return only that file.
|
||||
func GetFsNamedFileOK(ctx context.Context, in Params, fsName string) (newCtx context.Context, f fs.Fs, err error) {
|
||||
fsString, err := getFsName(in, fsName)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
f, err = cache.Get(ctx, fsString)
|
||||
if err == nil {
|
||||
return ctx, f, nil
|
||||
} else if !errors.Is(err, fs.ErrorIsFile) {
|
||||
return ctx, nil, err
|
||||
}
|
||||
// f points to the directory above the file so find the remote name
|
||||
_, fileName, err := fspath.Split(fsString)
|
||||
if err != nil {
|
||||
return ctx, f, err
|
||||
}
|
||||
ctx, fi := filter.AddConfig(ctx)
|
||||
if !fi.InActive() {
|
||||
return ctx, f, fmt.Errorf("can't limit to single files when using filters: %q", fileName)
|
||||
}
|
||||
// Limit transfers to this file
|
||||
err = fi.AddFile(fileName)
|
||||
if err != nil {
|
||||
return ctx, f, fmt.Errorf("failed to limit to single file: %w", err)
|
||||
}
|
||||
return ctx, f, nil
|
||||
}
|
||||
|
||||
// getConfigMap gets the config as a map from in and converts it to a
|
||||
// config string
|
||||
//
|
||||
|
|
|
@ -5,18 +5,26 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
"github.com/rclone/rclone/fs/cache"
|
||||
"github.com/rclone/rclone/fs/filter"
|
||||
"github.com/rclone/rclone/fstest/mockfs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func mockNewFs(t *testing.T) func() {
|
||||
f, err := mockfs.NewFs(context.Background(), "mock", "mock", nil)
|
||||
ctx := context.Background()
|
||||
f, err := mockfs.NewFs(ctx, "/", "", nil)
|
||||
require.NoError(t, err)
|
||||
cache.Put("/", f)
|
||||
f, err = mockfs.NewFs(ctx, "mock", "/", nil)
|
||||
require.NoError(t, err)
|
||||
cache.Put("mock:/", f)
|
||||
cache.Put(":mock:/", f)
|
||||
f, err = mockfs.NewFs(ctx, "mock", "dir/file.txt", nil)
|
||||
require.NoError(t, err)
|
||||
cache.PutErr("mock:dir/file.txt", f, fs.ErrorIsFile)
|
||||
return func() {
|
||||
cache.Clear()
|
||||
}
|
||||
|
@ -64,6 +72,40 @@ func TestGetFsNamedStruct(t *testing.T) {
|
|||
assert.NotNil(t, f)
|
||||
}
|
||||
|
||||
func TestGetFsNamedFileOK(t *testing.T) {
|
||||
defer mockNewFs(t)()
|
||||
ctx := context.Background()
|
||||
|
||||
in := Params{
|
||||
"potato": "/",
|
||||
}
|
||||
newCtx, f, err := GetFsNamedFileOK(ctx, in, "potato")
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, f)
|
||||
assert.Equal(t, ctx, newCtx)
|
||||
|
||||
in = Params{
|
||||
"sausage": "/",
|
||||
}
|
||||
newCtx, f, err = GetFsNamedFileOK(ctx, in, "potato")
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, f)
|
||||
assert.Equal(t, ctx, newCtx)
|
||||
|
||||
in = Params{
|
||||
"potato": "mock:dir/file.txt",
|
||||
}
|
||||
newCtx, f, err = GetFsNamedFileOK(ctx, in, "potato")
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, f)
|
||||
assert.NotEqual(t, ctx, newCtx)
|
||||
|
||||
fi := filter.GetConfig(newCtx)
|
||||
assert.False(t, fi.InActive())
|
||||
assert.True(t, fi.IncludeRemote("file.txt"))
|
||||
assert.False(t, fi.IncludeRemote("other.txt"))
|
||||
}
|
||||
|
||||
func TestGetConfigMap(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
in Params
|
||||
|
|
Loading…
Reference in a new issue