mirror of
https://github.com/rclone/rclone
synced 2024-12-22 13:03:02 +01:00
backend: unify NewFs path handling for wrapping remotes
Use the same function to join the root paths for the wrapping remotes alias, cache and crypt. The new function fspath.JoinRootPath is equivalent to path.Join, but if the first non empty element starts with "//", this is preserved to allow Windows network path to be used in these remotes.
This commit is contained in:
parent
411a6cc472
commit
1a40bceb1d
@ -2,13 +2,12 @@ package alias
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
"github.com/ncw/rclone/fs/config/configmap"
|
||||
"github.com/ncw/rclone/fs/config/configstruct"
|
||||
"github.com/ncw/rclone/fs/fspath"
|
||||
)
|
||||
|
||||
// Register with Fs
|
||||
@ -47,14 +46,9 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
||||
if strings.HasPrefix(opt.Remote, name+":") {
|
||||
return nil, errors.New("can't point alias remote at itself - check the value of the remote setting")
|
||||
}
|
||||
_, configName, fsPath, err := fs.ParseRemote(opt.Remote)
|
||||
fsInfo, configName, fsPath, config, err := fs.ConfigFs(opt.Remote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if configName == "local" {
|
||||
root = filepath.Join(fsPath, root)
|
||||
return fs.NewFs(root)
|
||||
}
|
||||
root = path.Join(fsPath, filepath.ToSlash(root))
|
||||
return fs.NewFs(configName + ":" + root)
|
||||
return fsInfo.NewFs(configName, fspath.JoinRootPath(fsPath, root), config)
|
||||
}
|
||||
|
3
backend/cache/cache.go
vendored
3
backend/cache/cache.go
vendored
@ -24,6 +24,7 @@ import (
|
||||
"github.com/ncw/rclone/fs/config/configmap"
|
||||
"github.com/ncw/rclone/fs/config/configstruct"
|
||||
"github.com/ncw/rclone/fs/config/obscure"
|
||||
"github.com/ncw/rclone/fs/fspath"
|
||||
"github.com/ncw/rclone/fs/hash"
|
||||
"github.com/ncw/rclone/fs/rc"
|
||||
"github.com/ncw/rclone/fs/walk"
|
||||
@ -363,7 +364,7 @@ func NewFs(name, rootPath string, m configmap.Mapper) (fs.Fs, error) {
|
||||
return nil, errors.Wrapf(err, "failed to parse remote %q to wrap", opt.Remote)
|
||||
}
|
||||
|
||||
remotePath := path.Join(wPath, rootPath)
|
||||
remotePath := fspath.JoinRootPath(wPath, rootPath)
|
||||
wrappedFs, wrapErr := wInfo.NewFs(wName, remotePath, wConfig)
|
||||
if wrapErr != nil && wrapErr != fs.ErrorIsFile {
|
||||
return nil, errors.Wrapf(wrapErr, "failed to make remote %s:%s to wrap", wName, remotePath)
|
||||
|
@ -4,7 +4,6 @@ package crypt
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -13,6 +12,7 @@ import (
|
||||
"github.com/ncw/rclone/fs/config/configmap"
|
||||
"github.com/ncw/rclone/fs/config/configstruct"
|
||||
"github.com/ncw/rclone/fs/config/obscure"
|
||||
"github.com/ncw/rclone/fs/fspath"
|
||||
"github.com/ncw/rclone/fs/hash"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -143,11 +143,11 @@ func NewFs(name, rpath string, m configmap.Mapper) (fs.Fs, error) {
|
||||
return nil, errors.Wrapf(err, "failed to parse remote %q to wrap", remote)
|
||||
}
|
||||
// Look for a file first
|
||||
remotePath := path.Join(wPath, cipher.EncryptFileName(rpath))
|
||||
remotePath := fspath.JoinRootPath(wPath, cipher.EncryptFileName(rpath))
|
||||
wrappedFs, err := wInfo.NewFs(wName, remotePath, wConfig)
|
||||
// if that didn't produce a file, look for a directory
|
||||
if err != fs.ErrorIsFile {
|
||||
remotePath = path.Join(wPath, cipher.EncryptDirName(rpath))
|
||||
remotePath = fspath.JoinRootPath(wPath, cipher.EncryptDirName(rpath))
|
||||
wrappedFs, err = wInfo.NewFs(wName, remotePath, wConfig)
|
||||
}
|
||||
if err != fs.ErrorIsFile && err != nil {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/ncw/rclone/fs/driveletter"
|
||||
)
|
||||
@ -48,3 +49,19 @@ func Split(remote string) (parent string, leaf string) {
|
||||
parent, leaf = path.Split(remotePath)
|
||||
return remoteName + parent, leaf
|
||||
}
|
||||
|
||||
// JoinRootPath joins any number of path elements into a single path, adding a
|
||||
// separating slash if necessary. The result is Cleaned; in particular,
|
||||
// all empty strings are ignored.
|
||||
// If the first non empty element has a leading "//" this is preserved.
|
||||
func JoinRootPath(elem ...string) string {
|
||||
for i, e := range elem {
|
||||
if e != "" {
|
||||
if strings.HasPrefix(e, "//") {
|
||||
return "/" + path.Clean(strings.Join(elem[i:], "/"))
|
||||
}
|
||||
return path.Clean(strings.Join(elem[i:], "/"))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -58,3 +58,32 @@ func TestSplit(t *testing.T) {
|
||||
assert.Equal(t, test.remote, gotParent+gotLeaf, fmt.Sprintf("%s: %q + %q != %q", test.remote, gotParent, gotLeaf, test.remote))
|
||||
}
|
||||
}
|
||||
func TestJoinRootPath(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
elements []string
|
||||
want string
|
||||
}{
|
||||
{nil, ""},
|
||||
{[]string{""}, ""},
|
||||
{[]string{"/"}, "/"},
|
||||
{[]string{"/", "/"}, "/"},
|
||||
{[]string{"/", "//"}, "/"},
|
||||
{[]string{"/root", ""}, "/root"},
|
||||
{[]string{"/root", "/"}, "/root"},
|
||||
{[]string{"/root", "//"}, "/root"},
|
||||
{[]string{"/a/b"}, "/a/b"},
|
||||
{[]string{"//", "/"}, "//"},
|
||||
{[]string{"//server", "path"}, "//server/path"},
|
||||
{[]string{"//server/sub", "path"}, "//server/sub/path"},
|
||||
{[]string{"//server", "//path"}, "//server/path"},
|
||||
{[]string{"//server/sub", "//path"}, "//server/sub/path"},
|
||||
{[]string{"", "//", "/"}, "//"},
|
||||
{[]string{"", "//server", "path"}, "//server/path"},
|
||||
{[]string{"", "//server/sub", "path"}, "//server/sub/path"},
|
||||
{[]string{"", "//server", "//path"}, "//server/path"},
|
||||
{[]string{"", "//server/sub", "//path"}, "//server/sub/path"},
|
||||
} {
|
||||
got := JoinRootPath(test.elements...)
|
||||
assert.Equal(t, test.want, got)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user