summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarin Ivanov <[email protected]>2022-08-15 04:24:23 +0300
committerMarin Ivanov <[email protected]>2022-08-15 04:24:23 +0300
commit43069c737dde59bd86e5b09c496d9df90f29d136 (patch)
tree8d6e81c36c0f16c9a5da2f90af31df6f08dd6bab
parent04200620823cf9b11e0185234429af6180110adc (diff)
Fid ReadDir and improve tests
-rw-r--r--file.go48
-rw-r--r--fileinfo.go9
-rw-r--r--fs.go29
-rw-r--r--fs_test.go149
4 files changed, 148 insertions, 87 deletions
diff --git a/file.go b/file.go
index ef952cb..13b58ee 100644
--- a/file.go
+++ b/file.go
@@ -5,8 +5,6 @@ import (
"io"
"os"
"path"
-
- "github.com/minio/minio-go/v7"
)
type File struct {
@@ -20,7 +18,9 @@ type File struct {
// implements io.Closer
func (f *File) Close() error {
- defer f.cancel()
+ if f.cancel != nil {
+ defer f.cancel()
+ }
if f.r != nil {
return f.r.Close()
}
@@ -70,50 +70,12 @@ func (f *File) Name() string {
return path.Base(f.key)
}
-func (f *File) readdir(count int, onlyDir bool) ([]os.FileInfo, error) {
- if !isDirPath(f.key) {
- return nil, ErrNotDirectory
- }
- if count == 0 {
- return []os.FileInfo{}, nil
- }
- ctx, cancel := f.fs.contextWithTimeout()
- defer cancel()
- objectsCh := f.fs.client.ListObjects(ctx, f.fs.bucket, minio.ListObjectsOptions{Prefix: f.key})
- n := 0
- lastDir := f.key
- results := make([]os.FileInfo, 0)
- for objectInfo := range objectsCh {
- base := path.Base(objectInfo.Key)
- dir := path.Dir(objectInfo.Key) + "/"
- if lastDir != dir {
- lastDir = dir
- results = append(results, &FileInfo{
- name: base,
- isDir: true,
- })
- if onlyDir {
- n += 1
- }
- }
- if !onlyDir {
- results = append(results, transformObjectInfo(objectInfo))
- n += 1
- }
- if n > count {
- break
- }
- }
-
- return results, nil
-}
-
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
- return f.readdir(count, false)
+ return f.fs.readdir(f.key, count, false)
}
func (f *File) Readdirnames(n int) ([]string, error) {
- results, err := f.readdir(n, true)
+ results, err := f.fs.readdir(f.key, n, true)
if err != nil {
return nil, err
}
diff --git a/fileinfo.go b/fileinfo.go
index c5a7f1d..4724919 100644
--- a/fileinfo.go
+++ b/fileinfo.go
@@ -48,10 +48,17 @@ func (fi *FileInfo) Sys() interface{} {
}
func transformObjectInfo(info minio.ObjectInfo) fs.FileInfo {
+ base := path.Base(info.Key)
+ isDir := isDirPath(info.Key)
+ if isDir {
+ base += "/"
+ }
+
return &FileInfo{
objectInfo: &info,
- name: path.Base(info.Key),
+ isDir: isDir,
+ name: base,
size: info.Size,
mtime: info.LastModified,
}
diff --git a/fs.go b/fs.go
index d886de8..9ee3c33 100644
--- a/fs.go
+++ b/fs.go
@@ -154,7 +154,7 @@ func (fs *Fs) RemoveAll(path string) error {
if !isDirPath(path) {
return ErrNotDirectory
}
- objectsCh := fs.client.ListObjects(ctx, fs.bucket, minio.ListObjectsOptions{Prefix: path})
+ objectsCh := fs.client.ListObjects(ctx, fs.bucket, minio.ListObjectsOptions{Prefix: path, Recursive: true})
errc := fs.client.RemoveObjects(ctx, fs.bucket, objectsCh, minio.RemoveObjectsOptions{})
for err := range errc {
if err.Err != nil {
@@ -242,6 +242,33 @@ func (fs *Fs) newObjectWriter(key string) (io.WriteCloser, context.CancelFunc, <
return w, cancel, errc
}
+func (fs *Fs) readdir(directory string, count int, onlyDir bool) ([]os.FileInfo, error) {
+ if !isDirPath(directory) {
+ return nil, ErrNotDirectory
+ }
+ if count == 0 {
+ return []os.FileInfo{}, nil
+ }
+ ctx, cancel := fs.contextWithTimeout()
+ defer cancel()
+ objectsCh := fs.client.ListObjects(ctx, fs.bucket, minio.ListObjectsOptions{Prefix: directory})
+ n := uint(0)
+ maxcount := uint(count)
+ results := make([]os.FileInfo, 0)
+ for objectInfo := range objectsCh {
+ if onlyDir && !isDirPath(objectInfo.Key) {
+ continue
+ }
+ results = append(results, transformObjectInfo(objectInfo))
+ n += 1
+ if n > maxcount {
+ break
+ }
+ }
+
+ return results, nil
+}
+
func transformError(err error) error {
resp, ok := err.(minio.ErrorResponse)
if !ok {
diff --git a/fs_test.go b/fs_test.go
index cbee404..2f670cf 100644
--- a/fs_test.go
+++ b/fs_test.go
@@ -9,10 +9,16 @@ import (
"github.com/spf13/afero"
)
+var (
+ testdata = []byte("testdata")
+)
+
func TestFsListBuckets(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
buckets, err := testListBuckets(afs.Fs.(*Fs))
is.NoErr(err)
is.Equal(len(buckets), 1)
@@ -20,40 +26,46 @@ func TestFsListBuckets(t *testing.T) {
func TestFsMkdir(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.Mkdir("test", 0o644)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.Mkdir("test", 0o644)
is.Equal(err, ErrUnsupported)
}
func TestFsMkdirAll(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.MkdirAll("test1/test2", 0o644)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.MkdirAll("test1/test2", 0o644)
is.Equal(err, ErrUnsupported)
}
func TestFsChmod(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.Chmod("test", 0o644)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.Chmod("test", 0o644)
is.Equal(err, ErrUnsupported)
}
func TestFsChown(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.Chown("test", 1000, 1000)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.Chown("test", 1000, 1000)
is.Equal(err, ErrUnsupported)
}
func TestFsChtimes(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
now := time.Now()
err = afs.Chtimes("test", now, now)
is.Equal(err, ErrUnsupported)
@@ -61,15 +73,20 @@ func TestFsChtimes(t *testing.T) {
func TestFsWriteFile(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.WriteFile("dir/file", []byte("testdata"), 0)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.WriteFile("dir/file", testdata, 0)
is.NoErr(err)
}
func TestFsStat(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
+ err = afs.WriteFile("dir/file", testdata, 0)
is.NoErr(err)
info, err := afs.Stat("dir/file")
is.NoErr(err)
@@ -79,54 +96,66 @@ func TestFsStat(t *testing.T) {
func TestFsStatNoExist(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
_, err = afs.Stat("dir/non-existent")
is.Equal(err, afero.ErrFileNotFound)
}
func TestFsReadFile(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
+ err = afs.WriteFile("dir/file", testdata, 0)
is.NoErr(err)
b, err := afs.ReadFile("dir/file")
is.NoErr(err)
- is.Equal(b, []byte("testdata"))
+ is.Equal(b, testdata)
}
func TestFsReadNoExist(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
_, err = afs.ReadFile("non-existent")
is.Equal(err, afero.ErrFileNotFound)
}
func TestFsRemove(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.Remove("dir/file")
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.Remove("dir/file")
is.NoErr(err)
}
func TestFsRemoveNoExist(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.Remove("non-existent")
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ err := afs.Remove("non-existent")
is.NoErr(err)
}
func TestFsRemoveAll(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.WriteFile("dir/file1", []byte("testdata"), 0)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
+ err = afs.WriteFile("dir/file1", testdata, 0)
is.NoErr(err)
- err = afs.WriteFile("dir/file2", []byte("testdata"), 0)
+ err = afs.WriteFile("dir/file2", testdata, 0)
is.NoErr(err)
- err = afs.WriteFile("persist/file0", []byte("testdata"), 0)
+ err = afs.WriteFile("persist/file0", testdata, 0)
is.NoErr(err)
err = afs.RemoveAll("dir/")
is.NoErr(err)
@@ -138,9 +167,11 @@ func TestFsRemoveAll(t *testing.T) {
func TestFsRename(t *testing.T) {
is := is.New(t)
- afs, err := newTestAfs()
- is.NoErr(err)
- err = afs.WriteFile("dir/file", []byte("testdata"), 0)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
+ err = afs.WriteFile("dir/file", testdata, 0)
is.NoErr(err)
err = afs.Rename("dir/file", "dir/file2")
is.NoErr(err)
@@ -152,10 +183,44 @@ func TestFsRename(t *testing.T) {
is.NoErr(err)
}
-func newTestAfs() (*afero.Afero, error) {
+func TestFsReadDir(t *testing.T) {
+ is := is.New(t)
+ afs, cleanup := newTestAfs()
+ defer cleanup()
+
+ var err error
+ err = afs.WriteFile("dir/file1", []byte(""), 0)
+ is.NoErr(err)
+ err = afs.WriteFile("dir/file2", []byte(""), 0)
+ is.NoErr(err)
+ err = afs.WriteFile("dir/subdir/file3", []byte(""), 0)
+ is.NoErr(err)
+ defer afs.RemoveAll("/")
+
+ infos, err := afs.ReadDir("dir/")
+ is.NoErr(err)
+ is.Equal(len(infos), 3)
+ is.Equal(infos[0].Name(), "file1")
+ is.Equal(infos[1].Name(), "file2")
+ is.Equal(infos[2].IsDir(), true)
+ is.Equal(infos[2].Name(), "subdir/")
+
+ f, err := afs.Open("dir/")
+ is.NoErr(err)
+ names, err := f.Readdirnames(-1)
+ is.NoErr(err)
+ is.Equal(names, []string{"subdir/"})
+}
+
+func newTestAfs() (*afero.Afero, func()) {
fs, err := NewFsFromURL("http://testuser:[email protected]:9000/test-bucket")
+ if err != nil {
+ panic("unexpected error")
+ }
afs := &afero.Afero{Fs: fs}
- return afs, err
+ return afs, func() {
+ afs.RemoveAll("/")
+ }
}
func testListBuckets(fs *Fs) ([]string, error) {