pkg/fileutil: add "ReadDirOption"

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
release-3.4
Gyuho Lee 2018-05-18 10:28:27 -07:00
parent ad4e8e9490
commit fa6d2e2d71
4 changed files with 138 additions and 47 deletions

View File

@ -20,7 +20,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"github.com/coreos/pkg/capnslog"
)
@ -32,9 +31,7 @@ const (
PrivateDirMode = 0700
)
var (
plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "pkg/fileutil")
)
var plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "pkg/fileutil")
// IsDirWriteable checks if dir is writable by writing and removing a file
// to dir. It returns nil if dir is writable.
@ -46,21 +43,6 @@ func IsDirWriteable(dir string) error {
return os.Remove(f)
}
// ReadDir returns the filenames in the given directory in sorted order.
func ReadDir(dirpath string) ([]string, error) {
dir, err := os.Open(dirpath)
if err != nil {
return nil, err
}
defer dir.Close()
names, err := dir.Readdirnames(-1)
if err != nil {
return nil, err
}
sort.Strings(names)
return names, nil
}
// 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 {

View File

@ -22,7 +22,6 @@ import (
"os"
"os/user"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
@ -58,33 +57,6 @@ func TestIsDirWriteable(t *testing.T) {
}
}
func TestReadDir(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
defer os.RemoveAll(tmpdir)
if err != nil {
t.Fatalf("unexpected ioutil.TempDir error: %v", err)
}
files := []string{"def", "abc", "xyz", "ghi"}
for _, f := range files {
var fh *os.File
fh, err = os.Create(filepath.Join(tmpdir, f))
if err != nil {
t.Fatalf("error creating file: %v", err)
}
if err = fh.Close(); err != nil {
t.Fatalf("error closing file: %v", err)
}
}
fs, err := ReadDir(tmpdir)
if err != nil {
t.Fatalf("error calling ReadDir: %v", err)
}
wfs := []string{"abc", "def", "ghi", "xyz"}
if !reflect.DeepEqual(fs, wfs) {
t.Fatalf("ReadDir: got %v, want %v", fs, wfs)
}
}
func TestCreateDirAll(t *testing.T) {
tmpdir, err := ioutil.TempDir(os.TempDir(), "foo")
if err != nil {

70
pkg/fileutil/read_dir.go Normal file
View File

@ -0,0 +1,70 @@
// Copyright 2018 The etcd Authors
//
// 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 fileutil
import (
"os"
"path/filepath"
"sort"
)
// ReadDirOp represents an read-directory operation.
type ReadDirOp struct {
ext string
}
// ReadDirOption configures archiver operations.
type ReadDirOption func(*ReadDirOp)
// WithExt filters file names by their extensions.
// (e.g. WithExt(".wal") to list only WAL files)
func WithExt(ext string) ReadDirOption {
return func(op *ReadDirOp) { op.ext = ext }
}
func (op *ReadDirOp) applyOpts(opts []ReadDirOption) {
for _, opt := range opts {
opt(op)
}
}
// ReadDir returns the filenames in the given directory in sorted order.
func ReadDir(d string, opts ...ReadDirOption) ([]string, error) {
op := &ReadDirOp{}
op.applyOpts(opts)
dir, err := os.Open(d)
if err != nil {
return nil, err
}
defer dir.Close()
names, err := dir.Readdirnames(-1)
if err != nil {
return nil, err
}
sort.Strings(names)
if op.ext != "" {
tss := make([]string, 0)
for _, v := range names {
if filepath.Ext(v) == op.ext {
tss = append(tss, v)
}
}
names = tss
}
return names, nil
}

View File

@ -0,0 +1,67 @@
// Copyright 2018 The etcd Authors
//
// 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 fileutil
import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
)
func TestReadDir(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
defer os.RemoveAll(tmpdir)
if err != nil {
t.Fatalf("unexpected ioutil.TempDir error: %v", err)
}
files := []string{"def", "abc", "xyz", "ghi"}
for _, f := range files {
writeFunc(t, filepath.Join(tmpdir, f))
}
fs, err := ReadDir(tmpdir)
if err != nil {
t.Fatalf("error calling ReadDir: %v", err)
}
wfs := []string{"abc", "def", "ghi", "xyz"}
if !reflect.DeepEqual(fs, wfs) {
t.Fatalf("ReadDir: got %v, want %v", fs, wfs)
}
files = []string{"def.wal", "abc.wal", "xyz.wal", "ghi.wal"}
for _, f := range files {
writeFunc(t, filepath.Join(tmpdir, f))
}
fs, err = ReadDir(tmpdir, WithExt(".wal"))
if err != nil {
t.Fatalf("error calling ReadDir: %v", err)
}
wfs = []string{"abc.wal", "def.wal", "ghi.wal", "xyz.wal"}
if !reflect.DeepEqual(fs, wfs) {
t.Fatalf("ReadDir: got %v, want %v", fs, wfs)
}
}
func writeFunc(t *testing.T, path string) {
fh, err := os.Create(path)
if err != nil {
t.Fatalf("error creating file: %v", err)
}
if err = fh.Close(); err != nil {
t.Fatalf("error closing file: %v", err)
}
}