forked from mirror/afero
fix Readdir behaviour for n > 0, fix RemoveAll
This commit is contained in:
parent
c64453ab4d
commit
10150bfa64
101
fs_test.go
101
fs_test.go
|
@ -16,6 +16,7 @@ package afero
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -288,6 +289,20 @@ func setupTestDir(t *testing.T) {
|
|||
}
|
||||
f.WriteString("Testfile 2 content")
|
||||
f.Close()
|
||||
|
||||
f, err = fs.Create(filepath.Join(testSubDir, "testfile3"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.WriteString("Testfile 3 content")
|
||||
f.Close()
|
||||
|
||||
f, err = fs.Create(filepath.Join(testSubDir, "testfile4"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.WriteString("Testfile 4 content")
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +330,81 @@ func TestReaddirnames(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReaddirSimple(t *testing.T) {
|
||||
for _, fs := range Fss {
|
||||
root, err := fs.Open(testDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rootInfo, err := root.Readdir(1)
|
||||
if err != nil {
|
||||
t.Log(myFileInfo(rootInfo))
|
||||
t.Error(err)
|
||||
}
|
||||
rootInfo, err = root.Readdir(5)
|
||||
if err != io.EOF {
|
||||
t.Log(myFileInfo(rootInfo))
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
sub, err := fs.Open(testSubDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
subInfo, err := sub.Readdir(5)
|
||||
if err != nil {
|
||||
t.Log(myFileInfo(subInfo))
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaddir(t *testing.T) {
|
||||
for num := 0; num < 6; num++ {
|
||||
outputs := make([]string, len(Fss))
|
||||
for i, fs := range Fss {
|
||||
root, err := fs.Open(testSubDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for j := 0; j < 6; j++ {
|
||||
info, err := root.Readdir(num)
|
||||
outputs[i] += fmt.Sprintf("%v Error: %v\n", myFileInfo(info), err)
|
||||
}
|
||||
}
|
||||
|
||||
fail := false
|
||||
for i, o := range outputs {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
if o != outputs[i-1] {
|
||||
fail = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if fail {
|
||||
t.Log("Readdir outputs not equal for Readdir(", num, ")")
|
||||
for i, o := range outputs {
|
||||
t.Log(Fss[i].Name())
|
||||
t.Log(o)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type myFileInfo []os.FileInfo
|
||||
|
||||
func (m myFileInfo) String() string {
|
||||
out := "Fileinfos:\n"
|
||||
for _, e := range m {
|
||||
out += " " + e.Name() + "\n"
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func TestReaddirAll(t *testing.T) {
|
||||
defer removeTestDir(t)
|
||||
for _, fs := range Fss {
|
||||
root, err := fs.Open(testDir)
|
||||
|
@ -389,12 +478,12 @@ func findNames(t *testing.T, root, sub []string, fs Fs) {
|
|||
}
|
||||
|
||||
func removeTestDir(t *testing.T) {
|
||||
// for _, fs := range Fss {
|
||||
// err := fs.RemoveAll(testDir)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
for _, fs := range Fss {
|
||||
err := fs.RemoveAll(testDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newFile(testName string, fs Fs, t *testing.T) (f File) {
|
||||
|
|
59
memfile.go
59
memfile.go
|
@ -35,14 +35,15 @@ type MemDir interface {
|
|||
|
||||
type InMemoryFile struct {
|
||||
sync.Mutex
|
||||
at int64
|
||||
name string
|
||||
data []byte
|
||||
memDir MemDir
|
||||
dir bool
|
||||
closed bool
|
||||
mode os.FileMode
|
||||
modtime time.Time
|
||||
at int64
|
||||
name string
|
||||
data []byte
|
||||
memDir MemDir
|
||||
dir bool
|
||||
closed bool
|
||||
mode os.FileMode
|
||||
modtime time.Time
|
||||
readDirCount int64
|
||||
}
|
||||
|
||||
func MemFileCreate(name string) *InMemoryFile {
|
||||
|
@ -51,6 +52,7 @@ func MemFileCreate(name string) *InMemoryFile {
|
|||
|
||||
func (f *InMemoryFile) Open() error {
|
||||
atomic.StoreInt64(&f.at, 0)
|
||||
atomic.StoreInt64(&f.readDirCount, 0)
|
||||
f.Lock()
|
||||
f.closed = false
|
||||
f.Unlock()
|
||||
|
@ -58,7 +60,6 @@ func (f *InMemoryFile) Open() error {
|
|||
}
|
||||
|
||||
func (f *InMemoryFile) Close() error {
|
||||
atomic.StoreInt64(&f.at, 0)
|
||||
f.Lock()
|
||||
f.closed = true
|
||||
f.Unlock()
|
||||
|
@ -74,29 +75,31 @@ func (f *InMemoryFile) Stat() (os.FileInfo, error) {
|
|||
}
|
||||
|
||||
func (f *InMemoryFile) Readdir(count int) (res []os.FileInfo, err error) {
|
||||
files := f.memDir.Files()
|
||||
limit := len(files)
|
||||
|
||||
if len(files) == 0 {
|
||||
return
|
||||
}
|
||||
var outLength int64
|
||||
|
||||
f.Lock()
|
||||
files := f.memDir.Files()[f.readDirCount:]
|
||||
if count > 0 {
|
||||
limit = count
|
||||
if len(files) < count {
|
||||
outLength = int64(len(files))
|
||||
} else {
|
||||
outLength = int64(count)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
} else {
|
||||
outLength = int64(len(files))
|
||||
}
|
||||
f.readDirCount += outLength
|
||||
f.Unlock()
|
||||
|
||||
res = make([]os.FileInfo, outLength)
|
||||
for i := range res {
|
||||
res[i], _ = files[i].Stat()
|
||||
}
|
||||
|
||||
if len(files) < limit {
|
||||
err = io.EOF
|
||||
}
|
||||
|
||||
res = make([]os.FileInfo, f.memDir.Len())
|
||||
|
||||
i := 0
|
||||
for _, file := range f.memDir.Files() {
|
||||
res[i], _ = file.Stat()
|
||||
i++
|
||||
}
|
||||
return res, nil
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (f *InMemoryFile) Readdirnames(n int) (names []string, err error) {
|
||||
|
|
20
memmap.go
20
memmap.go
|
@ -20,6 +20,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -65,9 +66,17 @@ func (m MemDirMap) Files() (files []File) {
|
|||
for _, f := range m {
|
||||
files = append(files, f)
|
||||
}
|
||||
sort.Sort(filesSorter(files))
|
||||
return files
|
||||
}
|
||||
|
||||
type filesSorter []File
|
||||
|
||||
// implement sort.Interface for []File
|
||||
func (s filesSorter) Len() int { return len(s) }
|
||||
func (s filesSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s filesSorter) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
|
||||
|
||||
func (m MemDirMap) Names() (names []string) {
|
||||
for x := range m {
|
||||
names = append(names, x)
|
||||
|
@ -95,6 +104,9 @@ func (m *MemMapFs) unRegisterWithParent(fileName string) {
|
|||
return
|
||||
}
|
||||
parent := m.findParent(f)
|
||||
if parent == nil {
|
||||
log.Fatal("parent of ", f.Name(), " is nil")
|
||||
}
|
||||
pmem := parent.(*InMemoryFile)
|
||||
pmem.memDir.Remove(f)
|
||||
}
|
||||
|
@ -113,11 +125,10 @@ func (m *MemMapFs) registerWithParent(f File) {
|
|||
if f == nil {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
parent := m.findParent(f)
|
||||
if parent == nil {
|
||||
pdir := filepath.Dir(path.Clean(f.Name()))
|
||||
err = m.lockfreeMkdir(pdir, 0777)
|
||||
err := m.lockfreeMkdir(pdir, 0777)
|
||||
if err != nil {
|
||||
log.Println("Mkdir error:", err)
|
||||
return
|
||||
|
@ -211,6 +222,10 @@ func (m *MemMapFs) Remove(name string) error {
|
|||
}
|
||||
|
||||
func (m *MemMapFs) RemoveAll(path string) error {
|
||||
m.lock()
|
||||
m.unRegisterWithParent(path)
|
||||
m.unlock()
|
||||
|
||||
m.rlock()
|
||||
defer m.runlock()
|
||||
|
||||
|
@ -218,7 +233,6 @@ func (m *MemMapFs) RemoveAll(path string) error {
|
|||
if strings.HasPrefix(p, path) {
|
||||
m.runlock()
|
||||
m.lock()
|
||||
m.unRegisterWithParent(p)
|
||||
delete(m.getData(), p)
|
||||
m.unlock()
|
||||
m.rlock()
|
||||
|
|
Loading…
Reference in New Issue