From 187faba3e02060ffd613885f5bf4b74c5eba983b Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Wed, 22 Jun 2016 14:58:53 -0700 Subject: [PATCH] pkg/fileutil: fix TouchDirAll, add CreateDirAll os.MkdirAll never returns os.ErrExist. And add another function to ensure deepest directory is empty. --- pkg/fileutil/fileutil.go | 24 +++++++++++++++++++++++- pkg/fileutil/fileutil_test.go | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go index ee3acad96..c963a7903 100644 --- a/pkg/fileutil/fileutil.go +++ b/pkg/fileutil/fileutil.go @@ -16,6 +16,7 @@ package fileutil import ( + "fmt" "io/ioutil" "os" "path" @@ -63,13 +64,34 @@ func ReadDir(dirpath string) ([]string, error) { // TouchDirAll is similar to os.MkdirAll. It creates directories with 0700 permission if any directory // does not exists. TouchDirAll also ensures the given directory is writable. func TouchDirAll(dir string) error { + // If path is already a directory, MkdirAll does nothing + // and returns nil. err := os.MkdirAll(dir, PrivateDirMode) - if err != nil && err != os.ErrExist { + if err != nil { + // if mkdirAll("a/text") and "text" is not + // a directory, this will return syscall.ENOTDIR return err } return IsDirWriteable(dir) } +// CreateDirAll is similar to TouchDirAll but returns error +// if the deepest directory was not empty. +func CreateDirAll(dir string) error { + err := TouchDirAll(dir) + if err == nil { + var ns []string + ns, err = ReadDir(dir) + if err != nil { + return err + } + if len(ns) != 0 { + err = fmt.Errorf("expected %q to be empty, got %q", dir, ns) + } + } + return err +} + func Exist(name string) bool { _, err := os.Stat(name) return err == nil diff --git a/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go index f0674cd9d..43644311c 100644 --- a/pkg/fileutil/fileutil_test.go +++ b/pkg/fileutil/fileutil_test.go @@ -21,6 +21,7 @@ import ( "path/filepath" "reflect" "runtime" + "strings" "testing" ) @@ -80,6 +81,27 @@ func TestReadDir(t *testing.T) { } } +func TestCreateDirAll(t *testing.T) { + tmpdir, err := ioutil.TempDir(os.TempDir(), "foo") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + tmpdir2 := filepath.Join(tmpdir, "testdir") + if err = CreateDirAll(tmpdir2); err != nil { + t.Fatal(err) + } + + if err = ioutil.WriteFile(filepath.Join(tmpdir2, "text.txt"), []byte("test text"), PrivateFileMode); err != nil { + t.Fatal(err) + } + + if err = CreateDirAll(tmpdir2); err == nil || !strings.Contains(err.Error(), "to be empty, got") { + t.Fatalf("unexpected error %v", err) + } +} + func TestExist(t *testing.T) { f, err := ioutil.TempFile(os.TempDir(), "fileutil") if err != nil {