2019-05-23 19:26:16 +08:00
|
|
|
// Utilities for accessing the Fs cache
|
2018-10-26 21:48:22 +08:00
|
|
|
|
|
|
|
package rc
|
|
|
|
|
|
|
|
import (
|
2020-11-05 23:18:51 +08:00
|
|
|
"context"
|
2021-03-30 23:12:46 +08:00
|
|
|
"errors"
|
2024-01-19 18:35:02 +08:00
|
|
|
"fmt"
|
2020-11-05 23:18:51 +08:00
|
|
|
|
2019-07-29 01:47:38 +08:00
|
|
|
"github.com/rclone/rclone/fs"
|
|
|
|
"github.com/rclone/rclone/fs/cache"
|
2021-03-30 23:12:46 +08:00
|
|
|
"github.com/rclone/rclone/fs/config/configmap"
|
2024-01-19 18:35:02 +08:00
|
|
|
"github.com/rclone/rclone/fs/filter"
|
|
|
|
"github.com/rclone/rclone/fs/fspath"
|
2018-10-26 21:48:22 +08:00
|
|
|
)
|
|
|
|
|
2024-01-19 18:35:02 +08:00
|
|
|
// 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)
|
2018-10-28 01:29:20 +08:00
|
|
|
if err != nil {
|
2021-03-30 23:12:46 +08:00
|
|
|
if !IsErrParamInvalid(err) {
|
2024-01-19 18:35:02 +08:00
|
|
|
return fsString, err
|
2021-03-30 23:12:46 +08:00
|
|
|
}
|
|
|
|
fsString, err = getConfigMap(in, fsName)
|
|
|
|
if err != nil {
|
2024-01-19 18:35:02 +08:00
|
|
|
return fsString, err
|
2021-03-30 23:12:46 +08:00
|
|
|
}
|
2018-10-28 01:29:20 +08:00
|
|
|
}
|
2024-01-19 18:35:02 +08:00
|
|
|
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
|
|
|
|
}
|
2020-11-05 23:18:51 +08:00
|
|
|
return cache.Get(ctx, fsString)
|
2018-10-28 01:29:20 +08:00
|
|
|
}
|
|
|
|
|
2024-01-19 18:35:02 +08:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2021-03-30 23:12:46 +08:00
|
|
|
// getConfigMap gets the config as a map from in and converts it to a
|
|
|
|
// config string
|
|
|
|
//
|
|
|
|
// It uses the special parameters _name to name the remote and _root
|
|
|
|
// to make the root of the remote.
|
|
|
|
func getConfigMap(in Params, fsName string) (fsString string, err error) {
|
|
|
|
var m configmap.Simple
|
|
|
|
err = in.GetStruct(fsName, &m)
|
|
|
|
if err != nil {
|
|
|
|
return fsString, err
|
|
|
|
}
|
|
|
|
pop := func(key string) string {
|
|
|
|
value := m[key]
|
|
|
|
delete(m, key)
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
Type := pop("type")
|
|
|
|
name := pop("_name")
|
|
|
|
root := pop("_root")
|
|
|
|
if name != "" {
|
|
|
|
fsString = name
|
|
|
|
} else if Type != "" {
|
|
|
|
fsString = ":" + Type
|
|
|
|
} else {
|
|
|
|
return fsString, errors.New(`couldn't find "type" or "_name" in JSON config definition`)
|
|
|
|
}
|
|
|
|
config := m.String()
|
|
|
|
if config != "" {
|
|
|
|
fsString += ","
|
|
|
|
fsString += config
|
|
|
|
}
|
|
|
|
fsString += ":"
|
|
|
|
fsString += root
|
|
|
|
return fsString, nil
|
|
|
|
}
|
|
|
|
|
2020-05-20 18:39:20 +08:00
|
|
|
// GetFs gets an fs.Fs named "fs" either from the cache or creates it afresh
|
2020-11-05 23:18:51 +08:00
|
|
|
func GetFs(ctx context.Context, in Params) (f fs.Fs, err error) {
|
|
|
|
return GetFsNamed(ctx, in, "fs")
|
2018-10-26 21:48:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetFsAndRemoteNamed gets the fsName parameter from in, makes a
|
|
|
|
// remote or fetches it from the cache then gets the remoteName
|
|
|
|
// parameter from in too.
|
2020-11-05 23:18:51 +08:00
|
|
|
func GetFsAndRemoteNamed(ctx context.Context, in Params, fsName, remoteName string) (f fs.Fs, remote string, err error) {
|
2018-10-26 21:48:22 +08:00
|
|
|
remote, err = in.GetString(remoteName)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2020-11-05 23:18:51 +08:00
|
|
|
f, err = GetFsNamed(ctx, in, fsName)
|
2018-10-26 21:48:22 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFsAndRemote gets the `fs` parameter from in, makes a remote or
|
|
|
|
// fetches it from the cache then gets the `remote` parameter from in
|
|
|
|
// too.
|
2020-11-05 23:18:51 +08:00
|
|
|
func GetFsAndRemote(ctx context.Context, in Params) (f fs.Fs, remote string, err error) {
|
|
|
|
return GetFsAndRemoteNamed(ctx, in, "fs", "remote")
|
2018-10-26 21:48:22 +08:00
|
|
|
}
|
2020-11-29 19:41:50 +08:00
|
|
|
|
|
|
|
func init() {
|
|
|
|
Add(Call{
|
|
|
|
Path: "fscache/clear",
|
|
|
|
Fn: rcCacheClear,
|
|
|
|
Title: "Clear the Fs cache.",
|
|
|
|
AuthRequired: true,
|
|
|
|
Help: `
|
|
|
|
This clears the fs cache. This is where remotes created from backends
|
|
|
|
are cached for a short while to make repeated rc calls more efficient.
|
|
|
|
|
|
|
|
If you change the parameters of a backend then you may want to call
|
|
|
|
this to clear an existing remote out of the cache before re-creating
|
|
|
|
it.
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the fs cache
|
|
|
|
func rcCacheClear(ctx context.Context, in Params) (out Params, err error) {
|
|
|
|
cache.Clear()
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
Add(Call{
|
|
|
|
Path: "fscache/entries",
|
|
|
|
Fn: rcCacheEntries,
|
|
|
|
Title: "Returns the number of entries in the fs cache.",
|
|
|
|
AuthRequired: true,
|
|
|
|
Help: `
|
|
|
|
This returns the number of entries in the fs cache.
|
|
|
|
|
|
|
|
Returns
|
|
|
|
- entries - number of items in the cache
|
|
|
|
`,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the Entries the fs cache
|
|
|
|
func rcCacheEntries(ctx context.Context, in Params) (out Params, err error) {
|
|
|
|
return Params{
|
|
|
|
"entries": cache.Entries(),
|
|
|
|
}, nil
|
|
|
|
}
|