This commit is contained in:
parent
60a6a40175
commit
50ba0fd079
@ -90,10 +90,6 @@ func (f *BasicFilesystem) unrooted(path string) string {
|
|||||||
return rel(path, f.root)
|
return rel(path, f.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rel(path, prefix string) string {
|
|
||||||
return strings.TrimPrefix(strings.TrimPrefix(path, prefix), string(PathSeparator))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *BasicFilesystem) Chmod(name string, mode FileMode) error {
|
func (f *BasicFilesystem) Chmod(name string, mode FileMode) error {
|
||||||
name, err := f.rooted(name)
|
name, err := f.rooted(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -490,3 +490,29 @@ func TestNewBasicFilesystem(t *testing.T) {
|
|||||||
t.Errorf(`newBasicFilesystem("relative/path").root == %q, expected absolutification`, fs.root)
|
t.Errorf(`newBasicFilesystem("relative/path").root == %q, expected absolutification`, fs.root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRel(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
root string
|
||||||
|
abs string
|
||||||
|
expectedRel string
|
||||||
|
}{
|
||||||
|
{"/", "/", ""},
|
||||||
|
{"/", "/test", "test"},
|
||||||
|
{"/", "/Test", "Test"},
|
||||||
|
{"/Test", "/Test/test", "test"},
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
for i := range testCases {
|
||||||
|
testCases[i].root = filepath.FromSlash(testCases[i].root)
|
||||||
|
testCases[i].abs = filepath.FromSlash(testCases[i].abs)
|
||||||
|
testCases[i].expectedRel = filepath.FromSlash(testCases[i].expectedRel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
if res := rel(tc.abs, tc.root); res != tc.expectedRel {
|
||||||
|
t.Errorf(`rel("%v", "%v") == "%v", expected "%v"`, tc.abs, tc.root, res, tc.expectedRel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,11 @@
|
|||||||
|
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func (BasicFilesystem) SymlinksSupported() bool {
|
func (BasicFilesystem) SymlinksSupported() bool {
|
||||||
return true
|
return true
|
||||||
@ -52,6 +56,20 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
|||||||
return []string{"/"}, nil
|
return []string{"/"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BasicFilesystem) resolveWin83(absPath string) string {
|
// unrootedChecked returns the path relative to the folder root (same as
|
||||||
return absPath
|
// unrooted). It panics if the given path is not a subpath and handles the
|
||||||
|
// special case when the given path is the folder root without a trailing
|
||||||
|
// pathseparator.
|
||||||
|
func (f *BasicFilesystem) unrootedChecked(absPath, root string) string {
|
||||||
|
if absPath+string(PathSeparator) == root {
|
||||||
|
return "."
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(absPath, root) {
|
||||||
|
panic(fmt.Sprintf("bug: Notify backend is processing a change outside of the filesystem root: f.root==%v, root==%v, path==%v", f.root, root, absPath))
|
||||||
|
}
|
||||||
|
return rel(absPath, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rel(path, prefix string) string {
|
||||||
|
return strings.TrimPrefix(strings.TrimPrefix(path, prefix), string(PathSeparator))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,10 +11,8 @@ package fs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/syncthing/notify"
|
"github.com/syncthing/notify"
|
||||||
)
|
)
|
||||||
@ -114,18 +112,3 @@ func (f *BasicFilesystem) eventType(notifyType notify.Event) EventType {
|
|||||||
}
|
}
|
||||||
return NonRemove
|
return NonRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
// unrootedChecked returns the path relative to the folder root (same as
|
|
||||||
// unrooted). It panics if the given path is not a subpath and handles the
|
|
||||||
// special case when the given path is the folder root without a trailing
|
|
||||||
// pathseparator.
|
|
||||||
func (f *BasicFilesystem) unrootedChecked(absPath, root string) string {
|
|
||||||
absPath = f.resolveWin83(absPath)
|
|
||||||
if absPath+string(PathSeparator) == root {
|
|
||||||
return "."
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(absPath, root) {
|
|
||||||
panic(fmt.Sprintf("bug: Notify backend is processing a change outside of the filesystem root: f.root==%v, root==%v, path==%v", f.root, root, absPath))
|
|
||||||
}
|
|
||||||
return rel(absPath, root)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -320,8 +320,12 @@ func TestWatchIssue4877(t *testing.T) {
|
|||||||
{name, NonRemove},
|
{name, NonRemove},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volName := filepath.VolumeName(testDirAbs)
|
||||||
|
if volName == "" {
|
||||||
|
t.Fatalf("Failed to get volume name for path %v", testDirAbs)
|
||||||
|
}
|
||||||
origTestFs := testFs
|
origTestFs := testFs
|
||||||
testFs = NewFilesystem(FilesystemTypeBasic, strings.ToLower(testDirAbs[:1])+strings.ToUpper(testDirAbs[1:]))
|
testFs = NewFilesystem(FilesystemTypeBasic, strings.ToLower(volName)+strings.ToUpper(testDirAbs[len(volName):]))
|
||||||
defer func() {
|
defer func() {
|
||||||
testFs = origTestFs
|
testFs = origTestFs
|
||||||
}()
|
}()
|
||||||
|
|||||||
@ -152,6 +152,28 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
|||||||
return drives, nil
|
return drives, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unrootedChecked returns the path relative to the folder root (same as
|
||||||
|
// unrooted). It panics if the given path is not a subpath and handles the
|
||||||
|
// special case when the given path is the folder root without a trailing
|
||||||
|
// pathseparator.
|
||||||
|
func (f *BasicFilesystem) unrootedChecked(absPath, root string) string {
|
||||||
|
absPath = f.resolveWin83(absPath)
|
||||||
|
lowerAbsPath := UnicodeLowercase(absPath)
|
||||||
|
lowerRoot := UnicodeLowercase(root)
|
||||||
|
if lowerAbsPath+string(PathSeparator) == lowerRoot {
|
||||||
|
return "."
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(lowerAbsPath, lowerRoot) {
|
||||||
|
panic(fmt.Sprintf("bug: Notify backend is processing a change outside of the filesystem root: f.root==%v, root==%v (lower), path==%v (lower)", f.root, lowerRoot, lowerAbsPath))
|
||||||
|
}
|
||||||
|
return rel(absPath, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
func rel(path, prefix string) string {
|
||||||
|
lowerRel := strings.TrimPrefix(strings.TrimPrefix(UnicodeLowercase(path), UnicodeLowercase(prefix)), string(PathSeparator))
|
||||||
|
return path[len(path)-len(lowerRel):]
|
||||||
|
}
|
||||||
|
|
||||||
func (f *BasicFilesystem) resolveWin83(absPath string) string {
|
func (f *BasicFilesystem) resolveWin83(absPath string) string {
|
||||||
if !isMaybeWin83(absPath) {
|
if !isMaybeWin83(absPath) {
|
||||||
return absPath
|
return absPath
|
||||||
@ -170,7 +192,8 @@ func (f *BasicFilesystem) resolveWin83(absPath string) string {
|
|||||||
}
|
}
|
||||||
// Failed getting the long path. Return the part of the path which is
|
// Failed getting the long path. Return the part of the path which is
|
||||||
// already a long path.
|
// already a long path.
|
||||||
for absPath = filepath.Dir(absPath); strings.HasPrefix(absPath, f.root); absPath = filepath.Dir(absPath) {
|
lowerRoot := UnicodeLowercase(f.root)
|
||||||
|
for absPath = filepath.Dir(absPath); strings.HasPrefix(UnicodeLowercase(absPath), lowerRoot); absPath = filepath.Dir(absPath) {
|
||||||
if !isMaybeWin83(absPath) {
|
if !isMaybeWin83(absPath) {
|
||||||
return absPath
|
return absPath
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,3 +90,48 @@ func TestIsWindows83(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRelUnrootedCheckedWindows(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
root string
|
||||||
|
abs string
|
||||||
|
expectedRel string
|
||||||
|
}{
|
||||||
|
{`c:\`, `c:\foo`, `foo`},
|
||||||
|
{`C:\`, `c:\foo`, `foo`},
|
||||||
|
{`C:\`, `C:\foo`, `foo`},
|
||||||
|
{`c:\`, `C:\foo`, `foo`},
|
||||||
|
{`\\?c:\`, `\\?c:\foo`, `foo`},
|
||||||
|
{`\\?C:\`, `\\?c:\foo`, `foo`},
|
||||||
|
{`\\?C:\`, `\\?C:\foo`, `foo`},
|
||||||
|
{`\\?c:\`, `\\?C:\foo`, `foo`},
|
||||||
|
{`c:\foo`, `c:\foo\bar`, `bar`},
|
||||||
|
{`c:\foo`, `c:\foo\bAr`, `bAr`},
|
||||||
|
{`c:\foO`, `c:\Foo\bar`, `bar`},
|
||||||
|
{`c:\foO`, `c:\fOo\bAr`, `bAr`},
|
||||||
|
{`c:\foO`, `c:\fOo`, ``},
|
||||||
|
{`C:\foO`, `c:\fOo`, ``},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
if res := rel(tc.abs, tc.root); res != tc.expectedRel {
|
||||||
|
t.Errorf(`rel("%v", "%v") == "%v", expected "%v"`, tc.abs, tc.root, res, tc.expectedRel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unrootedChecked really just wraps rel, and does not care about
|
||||||
|
// the actual root of that filesystem, but should not panic on these
|
||||||
|
// test cases.
|
||||||
|
fs := BasicFilesystem{root: tc.root}
|
||||||
|
if res := fs.unrootedChecked(tc.abs, tc.root); res != tc.expectedRel {
|
||||||
|
t.Errorf(`unrootedChecked("%v", "%v") == "%v", expected "%v"`, tc.abs, tc.root, res, tc.expectedRel)
|
||||||
|
}
|
||||||
|
fs = BasicFilesystem{root: strings.ToLower(tc.root)}
|
||||||
|
if res := fs.unrootedChecked(tc.abs, tc.root); res != tc.expectedRel {
|
||||||
|
t.Errorf(`unrootedChecked("%v", "%v") == "%v", expected "%v"`, tc.abs, tc.root, res, tc.expectedRel)
|
||||||
|
}
|
||||||
|
fs = BasicFilesystem{root: strings.ToUpper(tc.root)}
|
||||||
|
if res := fs.unrootedChecked(tc.abs, tc.root); res != tc.expectedRel {
|
||||||
|
t.Errorf(`unrootedChecked("%v", "%v") == "%v", expected "%v"`, tc.abs, tc.root, res, tc.expectedRel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user