Repository: spf13/afero (go)

Issue:
Amount of files read in UnionFile.Readdir does not match given argument
Currently, argument c in `UnionFile.Readdir` controls the upper bound of buffered files. To match behavior of `os.File.Readdir`, it should control amount of files read.
For example, if we have a directory with 10 files, first `UnionFile.Readdir(4)` would return 4 files. But next `UnionFile.Readdir(6)` would return `files[4:6]`, which would result in 2 files instead of remaining 6.

Pull request description:
Fix amount of files read in UnionFile.Readdir
To match behavior of `os.File.Readdir`, argument c in `UnionFile.Readdir` should control amount of files read, not the upper bound of buffered files.

Fixes #259

Patch:
diff --git a/unionFile.go b/unionFile.go
index eda9631..985363e 100644
--- a/unionFile.go
+++ b/unionFile.go
@@ -186,25 +186,22 @@ func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
 		}
 		f.files = append(f.files, merged...)
 	}
+	files := f.files[f.off:]
 
-	if c <= 0 && len(f.files) == 0 {
-		return f.files, nil
+	if c <= 0 {
+		return files, nil
 	}
 
-	if f.off >= len(f.files) {
+	if len(files) == 0 {
 		return nil, io.EOF
 	}
 
-	if c <= 0 {
-		return f.files[f.off:], nil
-	}
-
-	if c > len(f.files) {
-		c = len(f.files)
+	if c > len(files) {
+		c = len(files)
 	}
 
 	defer func() { f.off += c }()
-	return f.files[f.off:c], nil
+	return files[:c], nil
 }
 
 func (f *UnionFile) Readdirnames(c int) ([]string, error) {


Test patch:
diff --git a/composite_test.go b/composite_test.go
index bc915c2..9cfbed9 100644
--- a/composite_test.go
+++ b/composite_test.go
@@ -477,7 +477,8 @@ func TestUnionFileReaddirAskForTooMany(t *testing.T) {
 	base := &MemMapFs{}
 	overlay := &MemMapFs{}
 
-	for i := 0; i < 5; i++ {
+	const testFiles = 5
+	for i := 0; i < testFiles; i++ {
 		WriteFile(base, fmt.Sprintf("file%d.txt", i), []byte("afero"), 0777)
 	}
 
@@ -490,13 +491,24 @@ func TestUnionFileReaddirAskForTooMany(t *testing.T) {
 
 	defer f.Close()
 
-	names, err := f.Readdirnames(6)
+	// Read part of all files
+	wantNames := 3
+	names, err := f.Readdirnames(wantNames)
 	if err != nil {
 		t.Fatal(err)
 	}
+	if len(names) != wantNames {
+		t.Fatalf("got %d names %v, want %d", len(names), names, wantNames)
+	}
 
-	if len(names) != 5 {
-		t.Fatal(names)
+	// Try to read more files than remaining
+	wantNames = testFiles - len(names)
+	names, err = f.Readdirnames(wantNames + 1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(names) != wantNames {
+		t.Fatalf("got %d names %v, want %d", len(names), names, wantNames)
 	}
 
 	// End of directory