cleanRootPath used filepath.Abs which prepends the current directory, but the resulting absolute path does not always refer to the same directory as the original relative path - for example when the current directory is shadowed by a mount or has been removed. This made "rclone copy --links . ../dst" fail where "cp -ra . ../dst" succeeds. rclone now cleans the path lexically on non-Windows platforms instead, leaving relative roots relative so the OS resolves them against the live working directory. Windows still makes the path absolute as required for UNC long-path conversion.
59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
package local
|
||
|
||
import (
|
||
"runtime"
|
||
"testing"
|
||
|
||
"github.com/rclone/rclone/lib/encoder"
|
||
)
|
||
|
||
// Test Windows character replacements
|
||
var testsWindows = [][2]string{
|
||
{`c:\temp`, `c:\temp`},
|
||
{`\\?\UNC\theserver\dir\file.txt`, `\\?\UNC\theserver\dir\file.txt`},
|
||
{`//?/UNC/theserver/dir\file.txt`, `\\?\UNC\theserver\dir\file.txt`},
|
||
{`c:/temp`, `c:\temp`},
|
||
{`C:/temp/file.txt`, `C:\temp\file.txt`},
|
||
{`c:\!\"#¤%&/()=;:*^?+-`, `c:\!\"#¤%&\()=;:*^?+-`},
|
||
{`c:\<>"|?*:&\<>"|?*:&\<>"|?*:&`, `c:\<>"|?*:&\<>"|?*:&\<>"|?*:&`},
|
||
}
|
||
|
||
func TestCleanWindows(t *testing.T) {
|
||
if runtime.GOOS != "windows" {
|
||
t.Skipf("windows only")
|
||
}
|
||
for _, test := range testsWindows {
|
||
got := cleanRootPath(test[0], true, encoder.OS)
|
||
expect := test[1]
|
||
if got != expect {
|
||
t.Fatalf("got %q, expected %q", got, expect)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Relative roots must stay relative so the OS resolves them against the
|
||
// live working directory rather than a canonicalised string that may no
|
||
// longer refer to the same directory (#9510).
|
||
var testsRelative = [][2]string{
|
||
{".", "."},
|
||
{"./", "."},
|
||
{"sub/dir", "sub/dir"},
|
||
{"sub/dir/", "sub/dir"},
|
||
{"./sub/dir", "sub/dir"},
|
||
{"sub/../dir", "dir"},
|
||
{"..", ".."},
|
||
}
|
||
|
||
func TestCleanRootPathRelative(t *testing.T) {
|
||
if runtime.GOOS == "windows" {
|
||
t.Skipf("non-windows only")
|
||
}
|
||
for _, test := range testsRelative {
|
||
got := cleanRootPath(test[0], true, encoder.OS)
|
||
expect := test[1]
|
||
if got != expect {
|
||
t.Fatalf("got %q, expected %q", got, expect)
|
||
}
|
||
}
|
||
}
|