From 5282a79edac6842081bc55260928a5bbba1411a4 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 11 Mar 2016 19:47:44 -0800 Subject: [PATCH] cleanup: Remove unecessary packages and tests. Simplify. --- ...pi_suite_nix_test.go => api_suite_test.go} | 4 +- pkg/fs/api_suite_windows_test.go | 461 ------------------ pkg/fs/dir.go | 8 +- pkg/fs/fs-bucket-listobjects.go | 2 +- pkg/fs/fs-object.go | 3 +- pkg/ioutils/filepath.go | 143 ------ pkg/ioutils/ioutils_test.go | 43 -- 7 files changed, 7 insertions(+), 657 deletions(-) rename pkg/fs/{api_suite_nix_test.go => api_suite_test.go} (99%) delete mode 100644 pkg/fs/api_suite_windows_test.go delete mode 100644 pkg/ioutils/filepath.go delete mode 100644 pkg/ioutils/ioutils_test.go diff --git a/pkg/fs/api_suite_nix_test.go b/pkg/fs/api_suite_test.go similarity index 99% rename from pkg/fs/api_suite_nix_test.go rename to pkg/fs/api_suite_test.go index 2917a0ab5..f7e3ca31f 100644 --- a/pkg/fs/api_suite_nix_test.go +++ b/pkg/fs/api_suite_test.go @@ -1,7 +1,5 @@ -// +build linux darwin freebsd openbsd netbsd dragonfly - /* - * Minimalist Object Storage, (C) 2015 Minio, Inc. + * Minimalist Object Storage, (C) 2015, 2016 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/pkg/fs/api_suite_windows_test.go b/pkg/fs/api_suite_windows_test.go deleted file mode 100644 index fe9c525f9..000000000 --- a/pkg/fs/api_suite_windows_test.go +++ /dev/null @@ -1,461 +0,0 @@ -// +build windows - -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package fs - -import ( - "bytes" - "crypto/md5" - "encoding/base64" - "encoding/hex" - "encoding/xml" - "math/rand" - "strconv" - - "gopkg.in/check.v1" -) - -// APITestSuite - collection of API tests -func APITestSuite(c *check.C, create func() Filesystem) { - testMakeBucket(c, create) - testMultipleObjectCreation(c, create) - testPaging(c, create) - testObjectOverwriteWorks(c, create) - testNonExistantBucketOperations(c, create) - testBucketRecreateFails(c, create) - testPutObjectInSubdir(c, create) - testListBuckets(c, create) - testListBucketsOrder(c, create) - testListObjectsTestsForNonExistantBucket(c, create) - testNonExistantObjectInBucket(c, create) - testGetDirectoryReturnsObjectNotFound(c, create) - testDefaultContentType(c, create) - testMultipartObjectCreation(c, create) - testMultipartObjectAbort(c, create) -} - -func testMakeBucket(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) -} - -func testMultipartObjectCreation(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - uploadID, err := fs.NewMultipartUpload("bucket", "key") - c.Assert(err, check.IsNil) - - completedParts := CompleteMultipartUpload{} - completedParts.Part = make([]CompletePart, 0) - for i := 1; i <= 10; i++ { - randomPerm := rand.Perm(10) - randomString := "" - for _, num := range randomPerm { - randomString = randomString + strconv.Itoa(num) - } - - hasher := md5.New() - hasher.Write([]byte(randomString)) - expectedmd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) - expectedmd5Sumhex := hex.EncodeToString(hasher.Sum(nil)) - - var calculatedmd5sum string - calculatedmd5sum, err = fs.CreateObjectPart("bucket", "key", uploadID, expectedmd5Sum, i, int64(len(randomString)), - bytes.NewBufferString(randomString), nil) - c.Assert(err, check.IsNil) - c.Assert(calculatedmd5sum, check.Equals, expectedmd5Sumhex) - completedParts.Part = append(completedParts.Part, CompletePart{PartNumber: i, ETag: calculatedmd5sum}) - } - completedPartsBytes, e := xml.Marshal(completedParts) - c.Assert(e, check.IsNil) - objectInfo, err := fs.CompleteMultipartUpload("bucket", "key", uploadID, bytes.NewReader(completedPartsBytes), nil) - c.Assert(err, check.IsNil) - c.Assert(objectInfo.MD5Sum, check.Equals, "9b7d6f13ba00e24d0b02de92e814891b-10") -} - -func testMultipartObjectAbort(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - uploadID, err := fs.NewMultipartUpload("bucket", "key") - c.Assert(err, check.IsNil) - - parts := make(map[int]string) - for i := 1; i <= 10; i++ { - randomPerm := rand.Perm(10) - randomString := "" - for _, num := range randomPerm { - randomString = randomString + strconv.Itoa(num) - } - - hasher := md5.New() - hasher.Write([]byte(randomString)) - expectedmd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) - expectedmd5Sumhex := hex.EncodeToString(hasher.Sum(nil)) - - var calculatedmd5sum string - calculatedmd5sum, err = fs.CreateObjectPart("bucket", "key", uploadID, expectedmd5Sum, i, int64(len(randomString)), - bytes.NewBufferString(randomString), nil) - c.Assert(err, check.IsNil) - c.Assert(calculatedmd5sum, check.Equals, expectedmd5Sumhex) - parts[i] = calculatedmd5sum - } - err = fs.AbortMultipartUpload("bucket", "key", uploadID) - c.Assert(err, check.IsNil) -} - -func testMultipleObjectCreation(c *check.C, create func() Filesystem) { - objects := make(map[string][]byte) - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - for i := 0; i < 10; i++ { - randomPerm := rand.Perm(10) - randomString := "" - for _, num := range randomPerm { - randomString = randomString + strconv.Itoa(num) - } - - hasher := md5.New() - hasher.Write([]byte(randomString)) - expectedmd5Sum := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) - expectedmd5Sumhex := hex.EncodeToString(hasher.Sum(nil)) - - key := "obj" + strconv.Itoa(i) - objects[key] = []byte(randomString) - objectInfo, err := fs.CreateObject("bucket", key, expectedmd5Sum, int64(len(randomString)), bytes.NewBufferString(randomString), nil) - c.Assert(err, check.IsNil) - c.Assert(objectInfo.MD5Sum, check.Equals, expectedmd5Sumhex) - } - - for key, value := range objects { - var byteBuffer bytes.Buffer - _, err := fs.GetObject(&byteBuffer, "bucket", key, 0, 0) - c.Assert(err, check.IsNil) - c.Assert(byteBuffer.Bytes(), check.DeepEquals, value) - - metadata, err := fs.GetObjectInfo("bucket", key) - c.Assert(err, check.IsNil) - c.Assert(metadata.Size, check.Equals, int64(len(value))) - } -} - -func testPaging(c *check.C, create func() Filesystem) { - fs := create() - fs.MakeBucket("bucket") - result, err := fs.ListObjects("bucket", "", "", "", 0) - c.Assert(err, check.IsNil) - c.Assert(len(result.Objects), check.Equals, 0) - c.Assert(result.IsTruncated, check.Equals, false) - // check before paging occurs - for i := 0; i < 5; i++ { - key := "obj" + strconv.Itoa(i) - _, err = fs.CreateObject("bucket", key, "", int64(len(key)), bytes.NewBufferString(key), nil) - c.Assert(err, check.IsNil) - result, err = fs.ListObjects("bucket", "", "", "", 5) - c.Assert(err, check.IsNil) - c.Assert(len(result.Objects), check.Equals, i+1) - c.Assert(result.IsTruncated, check.Equals, false) - } - // check after paging occurs pages work - for i := 6; i <= 10; i++ { - key := "obj" + strconv.Itoa(i) - _, err = fs.CreateObject("bucket", key, "", int64(len(key)), bytes.NewBufferString(key), nil) - c.Assert(err, check.IsNil) - result, err = fs.ListObjects("bucket", "", "", "", 5) - c.Assert(err, check.IsNil) - c.Assert(len(result.Objects), check.Equals, 5) - c.Assert(result.IsTruncated, check.Equals, true) - } - // check paging with prefix at end returns less objects - { - _, err = fs.CreateObject("bucket", "newPrefix", "", int64(len("prefix1")), bytes.NewBufferString("prefix1"), nil) - c.Assert(err, check.IsNil) - fs.CreateObject("bucket", "newPrefix2", "", int64(len("prefix2")), bytes.NewBufferString("prefix2"), nil) - c.Assert(err, check.IsNil) - result, err = fs.ListObjects("bucket", "new", "", "", 5) - c.Assert(err, check.IsNil) - c.Assert(len(result.Objects), check.Equals, 2) - } - - // check ordering of pages - { - result, err = fs.ListObjects("bucket", "", "", "", 1000) - c.Assert(err, check.IsNil) - c.Assert(result.Objects[0].Name, check.Equals, "newPrefix") - c.Assert(result.Objects[1].Name, check.Equals, "newPrefix2") - c.Assert(result.Objects[2].Name, check.Equals, "obj0") - c.Assert(result.Objects[3].Name, check.Equals, "obj1") - c.Assert(result.Objects[4].Name, check.Equals, "obj10") - } - - // check delimited results with delimiter and prefix - { - _, err = fs.CreateObject("bucket", "this/is/delimited", "", int64(len("prefix1")), bytes.NewBufferString("prefix1"), nil) - c.Assert(err, check.IsNil) - _, err = fs.CreateObject("bucket", "this/is/also/a/delimited/file", "", int64(len("prefix2")), bytes.NewBufferString("prefix2"), nil) - c.Assert(err, check.IsNil) - result, err = fs.ListObjects("bucket", "this/is/", "", "/", 10) - c.Assert(err, check.IsNil) - c.Assert(len(result.Objects), check.Equals, 1) - c.Assert(result.Prefixes[0], check.Equals, "this/is/also/") - } - - // check delimited results with delimiter without prefix - { - result, err = fs.ListObjects("bucket", "", "", "/", 1000) - c.Assert(err, check.IsNil) - c.Assert(result.Objects[0].Name, check.Equals, "newPrefix") - c.Assert(result.Objects[1].Name, check.Equals, "newPrefix2") - c.Assert(result.Objects[2].Name, check.Equals, "obj0") - c.Assert(result.Objects[3].Name, check.Equals, "obj1") - c.Assert(result.Objects[4].Name, check.Equals, "obj10") - c.Assert(result.Prefixes[0], check.Equals, "this/") - } - - // check results with Marker - { - result, err = fs.ListObjects("bucket", "", "newPrefix", "", 3) - c.Assert(err, check.IsNil) - c.Assert(result.Objects[0].Name, check.Equals, "newPrefix2") - c.Assert(result.Objects[1].Name, check.Equals, "obj0") - c.Assert(result.Objects[2].Name, check.Equals, "obj1") - } - // check ordering of results with prefix - { - result, err = fs.ListObjects("bucket", "obj", "", "", 1000) - c.Assert(err, check.IsNil) - c.Assert(result.Objects[0].Name, check.Equals, "obj0") - c.Assert(result.Objects[1].Name, check.Equals, "obj1") - c.Assert(result.Objects[2].Name, check.Equals, "obj10") - c.Assert(result.Objects[3].Name, check.Equals, "obj2") - c.Assert(result.Objects[4].Name, check.Equals, "obj3") - } - // check ordering of results with prefix and no paging - { - result, err = fs.ListObjects("bucket", "new", "", "", 5) - c.Assert(err, check.IsNil) - c.Assert(result.Objects[0].Name, check.Equals, "newPrefix") - c.Assert(result.Objects[1].Name, check.Equals, "newPrefix2") - } -} - -func testObjectOverwriteWorks(c *check.C, create func() Filesystem) { - fs := create() - fs.MakeBucket("bucket") - - hasher1 := md5.New() - hasher1.Write([]byte("one")) - md5Sum1 := base64.StdEncoding.EncodeToString(hasher1.Sum(nil)) - md5Sum1hex := hex.EncodeToString(hasher1.Sum(nil)) - objectInfo, err := fs.CreateObject("bucket", "object", md5Sum1, int64(len("one")), bytes.NewBufferString("one"), nil) - c.Assert(err, check.IsNil) - c.Assert(md5Sum1hex, check.Equals, objectInfo.MD5Sum) - - hasher2 := md5.New() - hasher2.Write([]byte("three")) - md5Sum2 := base64.StdEncoding.EncodeToString(hasher2.Sum(nil)) - _, err = fs.CreateObject("bucket", "object", md5Sum2, int64(len("three")), bytes.NewBufferString("three"), nil) - c.Assert(err, check.IsNil) - - var bytesBuffer bytes.Buffer - length, err := fs.GetObject(&bytesBuffer, "bucket", "object", 0, 0) - c.Assert(err, check.IsNil) - c.Assert(length, check.Equals, int64(len("three"))) - c.Assert(string(bytesBuffer.Bytes()), check.Equals, "three") -} - -func testNonExistantBucketOperations(c *check.C, create func() Filesystem) { - fs := create() - _, err := fs.CreateObject("bucket", "object", "", int64(len("one")), bytes.NewBufferString("one"), nil) - c.Assert(err, check.Not(check.IsNil)) -} - -func testBucketRecreateFails(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("string") - c.Assert(err, check.IsNil) - err = fs.MakeBucket("string") - c.Assert(err, check.Not(check.IsNil)) -} - -func testPutObjectInSubdir(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - - hasher := md5.New() - hasher.Write([]byte("hello world")) - md5Sum1 := base64.StdEncoding.EncodeToString(hasher.Sum(nil)) - md5Sum1hex := hex.EncodeToString(hasher.Sum(nil)) - objectInfo, err := fs.CreateObject("bucket", "dir1/dir2/object", md5Sum1, int64(len("hello world")), bytes.NewBufferString("hello world"), nil) - c.Assert(err, check.IsNil) - c.Assert(objectInfo.MD5Sum, check.Equals, md5Sum1hex) - - var bytesBuffer bytes.Buffer - length, err := fs.GetObject(&bytesBuffer, "bucket", "dir1/dir2/object", 0, 0) - c.Assert(err, check.IsNil) - c.Assert(len(bytesBuffer.Bytes()), check.Equals, len("hello world")) - c.Assert(int64(len(bytesBuffer.Bytes())), check.Equals, length) -} - -func testListBuckets(c *check.C, create func() Filesystem) { - fs := create() - - // test empty list - buckets, err := fs.ListBuckets() - c.Assert(err, check.IsNil) - c.Assert(len(buckets), check.Equals, 0) - - // add one and test exists - err = fs.MakeBucket("bucket1") - c.Assert(err, check.IsNil) - - buckets, err = fs.ListBuckets() - c.Assert(len(buckets), check.Equals, 1) - c.Assert(err, check.IsNil) - - // add two and test exists - err = fs.MakeBucket("bucket2") - c.Assert(err, check.IsNil) - - buckets, err = fs.ListBuckets() - c.Assert(len(buckets), check.Equals, 2) - c.Assert(err, check.IsNil) - - // add three and test exists + prefix - err = fs.MakeBucket("bucket22") - - buckets, err = fs.ListBuckets() - c.Assert(len(buckets), check.Equals, 3) - c.Assert(err, check.IsNil) -} - -func testListBucketsOrder(c *check.C, create func() Filesystem) { - // if implementation contains a map, order of map keys will vary. - // this ensures they return in the same order each time - for i := 0; i < 10; i++ { - fs := create() - // add one and test exists - err := fs.MakeBucket("bucket1") - c.Assert(err, check.IsNil) - err = fs.MakeBucket("bucket2") - c.Assert(err, check.IsNil) - buckets, err := fs.ListBuckets() - c.Assert(err, check.IsNil) - c.Assert(len(buckets), check.Equals, 2) - c.Assert(buckets[0].Name, check.Equals, "bucket1") - c.Assert(buckets[1].Name, check.Equals, "bucket2") - } -} - -func testListObjectsTestsForNonExistantBucket(c *check.C, create func() Filesystem) { - fs := create() - result, err := fs.ListObjects("bucket", "", "", "", 1000) - c.Assert(err, check.Not(check.IsNil)) - c.Assert(result.IsTruncated, check.Equals, false) - c.Assert(len(result.Objects), check.Equals, 0) -} - -func testNonExistantObjectInBucket(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - - var byteBuffer bytes.Buffer - length, err := fs.GetObject(&byteBuffer, "bucket", "dir1", 0, 0) - c.Assert(length, check.Equals, int64(0)) - c.Assert(err, check.Not(check.IsNil)) - c.Assert(len(byteBuffer.Bytes()), check.Equals, 0) - switch err := err.ToGoError().(type) { - case ObjectNotFound: - { - c.Assert(err, check.ErrorMatches, "Object not found: bucket#dir1") - } - default: - { - c.Assert(err, check.Equals, "fails") - } - } -} - -func testGetDirectoryReturnsObjectNotFound(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - - _, err = fs.CreateObject("bucket", "dir1/dir2/object", "", int64(len("hello world")), bytes.NewBufferString("hello world"), nil) - c.Assert(err, check.IsNil) - - var byteBuffer bytes.Buffer - length, err := fs.GetObject(&byteBuffer, "bucket", "dir1", 0, 0) - c.Assert(length, check.Equals, int64(0)) - switch err := err.ToGoError().(type) { - case ObjectNotFound: - c.Assert(err.Bucket, check.Equals, "bucket") - c.Assert(err.Object, check.Equals, "dir1") - default: - // force a failure with a line number - c.Assert(err, check.Equals, "ObjectNotFound") - } - c.Assert(len(byteBuffer.Bytes()), check.Equals, 0) - - var byteBuffer2 bytes.Buffer - length, err = fs.GetObject(&byteBuffer, "bucket", "dir1/", 0, 0) - c.Assert(length, check.Equals, int64(0)) - switch err := err.ToGoError().(type) { - case ObjectNotFound: - c.Assert(err.Bucket, check.Equals, "bucket") - c.Assert(err.Object, check.Equals, "dir1/") - default: - // force a failure with a line number - c.Assert(err, check.Equals, "ObjectNotFound") - } - c.Assert(len(byteBuffer2.Bytes()), check.Equals, 0) -} - -func testDefaultContentType(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - - // test empty - _, err = fs.CreateObject("bucket", "one", "", int64(len("one")), bytes.NewBufferString("one"), nil) - metadata, err := fs.GetObjectInfo("bucket", "one") - c.Assert(err, check.IsNil) - c.Assert(metadata.ContentType, check.Equals, "application/octet-stream") -} - -func testContentMD5Set(c *check.C, create func() Filesystem) { - fs := create() - err := fs.MakeBucket("bucket") - c.Assert(err, check.IsNil) - - // test md5 invalid - badmd5Sum := "NWJiZjVhNTIzMjhlNzQzOWFlNmU3MTlkZmU3MTIyMDA" - calculatedmd5sum, err := fs.CreateObject("bucket", "one", badmd5Sum, int64(len("one")), bytes.NewBufferString("one"), nil) - c.Assert(err, check.Not(check.IsNil)) - c.Assert(calculatedmd5sum, check.Not(check.Equals), badmd5Sum) - - goodmd5sum := "NWJiZjVhNTIzMjhlNzQzOWFlNmU3MTlkZmU3MTIyMDA=" - calculatedmd5sum, err = fs.CreateObject("bucket", "two", goodmd5sum, int64(len("one")), bytes.NewBufferString("one"), nil) - c.Assert(err, check.IsNil) - c.Assert(calculatedmd5sum, check.Equals, goodmd5sum) -} diff --git a/pkg/fs/dir.go b/pkg/fs/dir.go index a9bec8a99..7bbc0194c 100644 --- a/pkg/fs/dir.go +++ b/pkg/fs/dir.go @@ -30,8 +30,8 @@ const ( listObjectsLimit = 1000 ) -// IsDirEmpty - returns whether given directory is empty or not -func IsDirEmpty(dirname string) (status bool, err error) { +// isDirEmpty - returns whether given directory is empty or not +func isDirEmpty(dirname string) (status bool, err error) { f, err := os.Open(dirname) if err == nil { defer f.Close() @@ -44,8 +44,8 @@ func IsDirEmpty(dirname string) (status bool, err error) { return } -// IsDirExist - returns whether given directory is exist or not -func IsDirExist(dirname string) (status bool, err error) { +// isDirExist - returns whether given directory is exist or not +func isDirExist(dirname string) (status bool, err error) { fi, err := os.Lstat(dirname) if err == nil { status = fi.IsDir() diff --git a/pkg/fs/fs-bucket-listobjects.go b/pkg/fs/fs-bucket-listobjects.go index 31956f1e4..c4dee341c 100644 --- a/pkg/fs/fs-bucket-listobjects.go +++ b/pkg/fs/fs-bucket-listobjects.go @@ -38,7 +38,7 @@ func (fs Filesystem) ListObjects(bucket, prefix, marker, delimiter string, maxKe bucket = fs.denormalizeBucket(bucket) - if status, err := IsDirExist(filepath.Join(fs.path, bucket)); !status { + if status, err := isDirExist(filepath.Join(fs.path, bucket)); !status { if err == nil { return result, probe.NewError(BucketNotFound{Bucket: bucket}) } else if os.IsNotExist(err) { diff --git a/pkg/fs/fs-object.go b/pkg/fs/fs-object.go index 07c91c8b7..dd45a90c3 100644 --- a/pkg/fs/fs-object.go +++ b/pkg/fs/fs-object.go @@ -31,7 +31,6 @@ import ( "github.com/minio/minio/pkg/atomic" "github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/disk" - "github.com/minio/minio/pkg/ioutils" "github.com/minio/minio/pkg/mimedb" "github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/s3/signature4" @@ -334,7 +333,7 @@ func deleteObjectPath(basePath, deletePath, bucket, object string) *probe.Error } if pathSt.IsDir() { // Verify if directory is empty. - empty, e := ioutils.IsDirEmpty(deletePath) + empty, e := isDirEmpty(deletePath) if e != nil { return probe.NewError(e) } diff --git a/pkg/ioutils/filepath.go b/pkg/ioutils/filepath.go deleted file mode 100644 index 9a4b84f7d..000000000 --- a/pkg/ioutils/filepath.go +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ioutils - -import ( - "errors" - "io" - "os" - "path/filepath" - "sort" -) - -// IsDirEmpty Check if a directory is empty -func IsDirEmpty(dirname string) (status bool, err error) { - f, err := os.Open(dirname) - if err == nil { - defer f.Close() - if _, err = f.Readdirnames(1); err == io.EOF { - status = true - err = nil - } - } - - return -} - -// FTW walks the file tree rooted at root, calling walkFn for each file or -// directory in the tree, including root. -func FTW(root string, walkFn FTWFunc) error { - info, err := os.Lstat(root) - if err != nil { - return walkFn(root, nil, err) - } - return walk(root, info, walkFn) -} - -// byName implements sort.Interface for sorting os.FileInfo list. -type byName []os.FileInfo - -func (f byName) Len() int { return len(f) } -func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } -func (f byName) Less(i, j int) bool { - n1 := f[i].Name() - if f[i].IsDir() { - n1 = n1 + string(os.PathSeparator) - } - - n2 := f[j].Name() - if f[i].IsDir() { - n2 = n2 + string(os.PathSeparator) - } - - return n1 < n2 -} - -// readDir reads the directory named by dirname and returns -// a sorted list of directory entries. -func readDir(dirname string) (fi []os.FileInfo, err error) { - f, err := os.Open(dirname) - if err == nil { - defer f.Close() - if fi, err = f.Readdir(-1); fi != nil { - sort.Sort(byName(fi)) - } - } - - return -} - -// FTWFunc is the type of the function called for each file or directory -// visited by Walk. The path argument contains the argument to Walk as a -// prefix; that is, if Walk is called with "dir", which is a directory -// containing the file "a", the walk function will be called with argument -// "dir/a". The info argument is the os.FileInfo for the named path. -type FTWFunc func(path string, info os.FileInfo, err error) error - -// ErrSkipDir is used as a return value from WalkFuncs to indicate that -// the directory named in the call is to be skipped. It is not returned -// as an error by any function. -var ErrSkipDir = errors.New("skip this directory") - -// ErrSkipFile is used as a return value from WalkFuncs to indicate that -// the file named in the call is to be skipped. It is not returned -// as an error by any function. -var ErrSkipFile = errors.New("skip this file") - -// ErrDirNotEmpty is used to throw error on directories which have atleast one regular -// file or a symlink left -var ErrDirNotEmpty = errors.New("directory not empty") - -// walk recursively descends path, calling walkFn. -func walk(path string, info os.FileInfo, walkFn FTWFunc) error { - err := walkFn(path, info, nil) - if err != nil { - if info.Mode().IsDir() && err == ErrSkipDir { - return nil - } - if info.Mode().IsRegular() && err == ErrSkipFile { - return nil - } - return err - } - - if !info.IsDir() { - return nil - } - - fis, err := readDir(path) - if err != nil { - return walkFn(path, info, err) - } - for _, fileInfo := range fis { - filename := filepath.Join(path, fileInfo.Name()) - if err != nil { - if err = walkFn(filename, fileInfo, err); err != nil && err != ErrSkipDir && err != ErrSkipFile { - return err - } - } else { - err = walk(filename, fileInfo, walkFn) - if err != nil { - if err == ErrSkipDir || err == ErrSkipFile { - return nil - } - return err - } - } - } - return nil -} diff --git a/pkg/ioutils/ioutils_test.go b/pkg/ioutils/ioutils_test.go deleted file mode 100644 index d316959f4..000000000 --- a/pkg/ioutils/ioutils_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ioutils_test - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/minio/minio/pkg/ioutils" - - . "gopkg.in/check.v1" -) - -func Test(t *testing.T) { TestingT(t) } - -type MySuite struct{} - -var _ = Suite(&MySuite{}) - -func (s *MySuite) TestIoutils(c *C) { - path, err := ioutil.TempDir(os.TempDir(), "minio-ioutils_test") - c.Assert(err, IsNil) - defer os.RemoveAll(path) - - status, err := ioutils.IsDirEmpty(path) - c.Assert(err, IsNil) - c.Assert(status, Equals, true) -}