mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
lib/fs: Improve IsParent (#5658)
This commit is contained in:
parent
926e9228ed
commit
e302ccf4b4
@ -8,6 +8,7 @@ package fs
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -106,3 +107,66 @@ func TestFileModeString(t *testing.T) {
|
||||
t.Fatalf("Got %v, expected %v", fm.String(), exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsParent(t *testing.T) {
|
||||
test := func(path, parent string, expected bool) {
|
||||
t.Helper()
|
||||
path = filepath.FromSlash(path)
|
||||
parent = filepath.FromSlash(parent)
|
||||
if res := IsParent(path, parent); res != expected {
|
||||
t.Errorf(`Unexpected result: IsParent("%v", "%v"): %v should be %v`, path, parent, res, expected)
|
||||
}
|
||||
}
|
||||
testBoth := func(path, parent string, expected bool) {
|
||||
t.Helper()
|
||||
test(path, parent, expected)
|
||||
if runtime.GOOS == "windows" {
|
||||
test("C:/"+path, "C:/"+parent, expected)
|
||||
} else {
|
||||
test("/"+path, "/"+parent, expected)
|
||||
}
|
||||
}
|
||||
|
||||
// rel - abs
|
||||
for _, parent := range []string{"/", "/foo", "/foo/bar"} {
|
||||
for _, path := range []string{"", ".", "foo", "foo/bar", "bas", "bas/baz"} {
|
||||
if runtime.GOOS == "windows" {
|
||||
parent = "C:/" + parent
|
||||
}
|
||||
test(parent, path, false)
|
||||
test(path, parent, false)
|
||||
}
|
||||
}
|
||||
|
||||
// equal
|
||||
for i, path := range []string{"/", "/foo", "/foo/bar", "", ".", "foo", "foo/bar"} {
|
||||
if i < 3 && runtime.GOOS == "windows" {
|
||||
path = "C:" + path
|
||||
}
|
||||
test(path, path, false)
|
||||
}
|
||||
|
||||
test("", ".", false)
|
||||
test(".", "", false)
|
||||
for _, parent := range []string{"", "."} {
|
||||
for _, path := range []string{"foo", "foo/bar"} {
|
||||
test(path, parent, true)
|
||||
test(parent, path, false)
|
||||
}
|
||||
}
|
||||
for _, parent := range []string{"foo", "foo/bar"} {
|
||||
for _, path := range []string{"bar", "bar/foo"} {
|
||||
testBoth(path, parent, false)
|
||||
testBoth(parent, path, false)
|
||||
}
|
||||
}
|
||||
for _, parent := range []string{"foo", "foo/bar"} {
|
||||
for _, path := range []string{"foo/bar/baz", "foo/bar/baz/bas"} {
|
||||
testBoth(path, parent, true)
|
||||
testBoth(parent, path, false)
|
||||
if runtime.GOOS == "windows" {
|
||||
test("C:/"+path, "D:/"+parent, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,11 +78,25 @@ func WindowsInvalidFilename(name string) bool {
|
||||
return strings.ContainsAny(name, windowsDisallowedCharacters)
|
||||
}
|
||||
|
||||
// IsParent compares paths purely lexicographically, meaning it returns false
|
||||
// if path and parent aren't both absolute or relative.
|
||||
func IsParent(path, parent string) bool {
|
||||
if len(parent) == 0 {
|
||||
if parent == path {
|
||||
// Twice the same root on windows would not be caught at the end.
|
||||
return false
|
||||
}
|
||||
if filepath.IsAbs(path) != filepath.IsAbs(parent) {
|
||||
return false
|
||||
}
|
||||
if parent == "" || parent == "." {
|
||||
// The empty string is the parent of everything except the empty
|
||||
// string. (Avoids panic in the next step.)
|
||||
return len(path) > 0
|
||||
// string and ".". (Avoids panic in the last step.)
|
||||
return path != "" && path != "."
|
||||
}
|
||||
if parent == "/" {
|
||||
// The root is the parent of everything except itself, which would
|
||||
// not be caught below.
|
||||
return path != "/"
|
||||
}
|
||||
if parent[len(parent)-1] != PathSeparator {
|
||||
parent += string(PathSeparator)
|
||||
|
Loading…
Reference in New Issue
Block a user