forked from mirror/afero
Normalize Paths so "/boo/" and "/boo" are the same
This commit is contained in:
parent
75dc847d59
commit
3a224e9827
34
memmap.go
34
memmap.go
|
@ -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}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue