Normalize Paths so "/boo/" and "/boo" are the same

This commit is contained in:
Steve Francia 2015-12-02 16:28:58 -05:00
parent 75dc847d59
commit 3a224e9827
2 changed files with 61 additions and 0 deletions

View File

@ -91,6 +91,7 @@ func (m MemDirMap) Names() (names []string) {
func (MemMapFs) Name() string { return "MemMapFS" } func (MemMapFs) Name() string { return "MemMapFS" }
func (m *MemMapFs) Create(name string) (File, error) { func (m *MemMapFs) Create(name string) (File, error) {
name = normalizePath(name)
m.lock() m.lock()
file := MemFileCreate(name) file := MemFileCreate(name)
m.getData()[name] = file m.getData()[name] = file
@ -158,6 +159,7 @@ func (m *MemMapFs) registerWithParent(f File) {
} }
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error { func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
name = normalizePath(name)
x, ok := m.getData()[name] x, ok := m.getData()[name]
if ok { if ok {
// Only return ErrFileExists if it's a file, not a directory. // Only return ErrFileExists if it's a file, not a directory.
@ -177,6 +179,8 @@ func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
} }
func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error { func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
name = normalizePath(name)
m.rlock() m.rlock()
x, ok := m.getData()[name] x, ok := m.getData()[name]
m.runlock() m.runlock()
@ -203,7 +207,23 @@ func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
return m.Mkdir(path, 0777) return m.Mkdir(path, 0777)
} }
// Handle some relative paths
func normalizePath(path string) string {
path = filepath.Clean(path)
switch path {
case ".":
return "/"
case "..":
return "/"
default:
return path
}
}
func (m *MemMapFs) Open(name string) (File, error) { func (m *MemMapFs) Open(name string) (File, error) {
name = normalizePath(name)
m.rlock() m.rlock()
f, ok := m.getData()[name] f, ok := m.getData()[name]
ff, ok := f.(*InMemoryFile) ff, ok := f.(*InMemoryFile)
@ -220,6 +240,7 @@ func (m *MemMapFs) Open(name string) (File, error) {
} }
func (m *MemMapFs) lockfreeOpen(name string) (File, error) { func (m *MemMapFs) lockfreeOpen(name string) (File, error) {
name = normalizePath(name)
f, ok := m.getData()[name] f, ok := m.getData()[name]
ff, ok := f.(*InMemoryFile) ff, ok := f.(*InMemoryFile)
if ok { if ok {
@ -258,6 +279,8 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
} }
func (m *MemMapFs) Remove(name string) error { func (m *MemMapFs) Remove(name string) error {
name = normalizePath(name)
m.lock() m.lock()
defer m.unlock() defer m.unlock()
@ -271,6 +294,7 @@ func (m *MemMapFs) Remove(name string) error {
} }
func (m *MemMapFs) RemoveAll(path string) error { func (m *MemMapFs) RemoveAll(path string) error {
path = normalizePath(path)
m.lock() m.lock()
m.unRegisterWithParent(path) m.unRegisterWithParent(path)
m.unlock() m.unlock()
@ -291,6 +315,13 @@ func (m *MemMapFs) RemoveAll(path string) error {
} }
func (m *MemMapFs) Rename(oldname, newname string) error { func (m *MemMapFs) Rename(oldname, newname string) error {
oldname = normalizePath(oldname)
newname = normalizePath(newname)
if oldname == newname {
return nil
}
m.rlock() m.rlock()
defer m.runlock() defer m.runlock()
if _, ok := m.getData()[oldname]; ok { if _, ok := m.getData()[oldname]; ok {
@ -315,6 +346,7 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
} }
func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
name = normalizePath(name)
f, err := m.Open(name) f, err := m.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -323,6 +355,7 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
} }
func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
name = normalizePath(name)
f, ok := m.getData()[name] f, ok := m.getData()[name]
if !ok { if !ok {
return &os.PathError{"chmod", name, ErrFileNotFound} return &os.PathError{"chmod", name, ErrFileNotFound}
@ -340,6 +373,7 @@ func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
} }
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error { func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
name = normalizePath(name)
f, ok := m.getData()[name] f, ok := m.getData()[name]
if !ok { if !ok {
return &os.PathError{"chtimes", name, ErrFileNotFound} return &os.PathError{"chtimes", name, ErrFileNotFound}

27
memmap_test.go Normal file
View File

@ -0,0 +1,27 @@
package afero
import "testing"
func TestNormalizePath(t *testing.T) {
type test struct {
input string
expected string
}
data := []test{
{".", "/"},
{".", "/"},
{"./", "/"},
{"..", "/"},
{"../", "/"},
{"./..", "/"},
{"./../", "/"},
}
for i, d := range data {
cpath := normalizePath(d.input)
if d.expected != cpath {
t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, cpath)
}
}
}