diff --git a/fs/fspath/path.go b/fs/fspath/path.go index 8c76aeae1..c32377f53 100644 --- a/fs/fspath/path.go +++ b/fs/fspath/path.go @@ -259,6 +259,27 @@ loop: return parsed, nil } +// SplitFs splits a remote a remoteName and an remotePath. +// +// SplitFs("remote:path/to/file") -> ("remote:", "path/to/file") +// SplitFs("/to/file") -> ("", "/to/file") +// +// If it returns remoteName as "" then remotePath is a local path +// +// The returned values have the property that remoteName + remotePath == +// remote (except under Windows where \ will be translated into /) +func SplitFs(remote string) (remoteName string, remotePath string, err error) { + parsed, err := Parse(remote) + if err != nil { + return "", "", err + } + remoteName, remotePath = parsed.ConfigString, parsed.Path + if remoteName != "" { + remoteName += ":" + } + return remoteName, remotePath, nil +} + // Split splits a remote into a parent and a leaf // // if it returns leaf as an empty string then remote is a directory @@ -268,14 +289,10 @@ loop: // The returned values have the property that parent + leaf == remote // (except under Windows where \ will be translated into /) func Split(remote string) (parent string, leaf string, err error) { - parsed, err := Parse(remote) + remoteName, remotePath, err := SplitFs(remote) if err != nil { return "", "", err } - remoteName, remotePath := parsed.ConfigString, parsed.Path - if remoteName != "" { - remoteName += ":" - } // Construct new remote name without last segment parent, leaf = path.Split(remotePath) return remoteName + parent, leaf, nil diff --git a/fs/fspath/path_test.go b/fs/fspath/path_test.go index d9c846153..4319913b3 100644 --- a/fs/fspath/path_test.go +++ b/fs/fspath/path_test.go @@ -324,6 +324,47 @@ func TestParse(t *testing.T) { } } +func TestSplitFs(t *testing.T) { + for _, test := range []struct { + remote, wantRemoteName, wantRemotePath string + wantErr error + }{ + {"", "", "", errCantBeEmpty}, + + {"remote:", "remote:", "", nil}, + {"remote:potato", "remote:", "potato", nil}, + {"remote:/", "remote:", "/", nil}, + {"remote:/potato", "remote:", "/potato", nil}, + {"remote:/potato/potato", "remote:", "/potato/potato", nil}, + {"remote:potato/sausage", "remote:", "potato/sausage", nil}, + {"rem.ote:potato/sausage", "", "", errInvalidCharacters}, + + {":remote:", ":remote:", "", nil}, + {":remote:potato", ":remote:", "potato", nil}, + {":remote:/", ":remote:", "/", nil}, + {":remote:/potato", ":remote:", "/potato", nil}, + {":remote:/potato/potato", ":remote:", "/potato/potato", nil}, + {":remote:potato/sausage", ":remote:", "potato/sausage", nil}, + {":rem[ote:potato/sausage", "", "", errInvalidCharacters}, + + {"/", "", "/", nil}, + {"/root", "", "/root", nil}, + {"/a/b", "", "/a/b", nil}, + {"root", "", "root", nil}, + {"a/b", "", "a/b", nil}, + {"root/", "", "root/", nil}, + {"a/b/", "", "a/b/", nil}, + } { + gotRemoteName, gotRemotePath, gotErr := SplitFs(test.remote) + assert.Equal(t, test.wantErr, gotErr) + assert.Equal(t, test.wantRemoteName, gotRemoteName, test.remote) + assert.Equal(t, test.wantRemotePath, gotRemotePath, test.remote) + if gotErr == nil { + assert.Equal(t, test.remote, gotRemoteName+gotRemotePath, fmt.Sprintf("%s: %q + %q != %q", test.remote, gotRemoteName, gotRemotePath, test.remote)) + } + } +} + func TestSplit(t *testing.T) { for _, test := range []struct { remote, wantParent, wantLeaf string