From 2788f0dbd16903de03cb8186e5c7d97b69ad387b Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Thu, 7 Nov 2013 09:25:44 +1100 Subject: [PATCH] Add FileSystem and WalkFS Closes #1 --- filesystem.go | 36 ++++++++++++++++++++++++++++++++++++ walk.go | 19 +++++++++++++------ 2 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 filesystem.go diff --git a/filesystem.go b/filesystem.go new file mode 100644 index 0000000..f1c4805 --- /dev/null +++ b/filesystem.go @@ -0,0 +1,36 @@ +package fs + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +// FileSystem defines the methods of an abstract filesystem. +type FileSystem interface { + + // ReadDir reads the directory named by dirname and returns a + // list of directory entries. + ReadDir(dirname string) ([]os.FileInfo, error) + + // Lstat returns a FileInfo describing the named file. If the file is a + // symbolic link, the returned FileInfo describes the symbolic link. Lstat + // makes no attempt to follow the link. + Lstat(name string) (os.FileInfo, error) + + // Join joins any number of path elements into a single path, adding a + // separator if necessary. The result is Cleaned; in particular, all + // empty strings are ignored. + // + // The separator is FileSystem specific. + Join(elem ...string) string +} + +// fs represents a FileSystem provided by the os package. +type fs struct{} + +func (f *fs) ReadDir(dirname string) ([]os.FileInfo, error) { return ioutil.ReadDir(dirname) } + +func (f *fs) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } + +func (f *fs) Join(elem ...string) string { return filepath.Join(elem...) } diff --git a/walk.go b/walk.go index 36541c9..6ffa1e0 100644 --- a/walk.go +++ b/walk.go @@ -2,9 +2,7 @@ package fs import ( - "io/ioutil" "os" - "path/filepath" ) // Walker provides a convenient interface for iterating over the @@ -15,6 +13,7 @@ import ( // but means that for very large directories Walker can be inefficient. // Walker does not follow symbolic links. type Walker struct { + fs FileSystem cur item stack []item descend bool @@ -28,8 +27,16 @@ type item struct { // Walk returns a new Walker rooted at root. func Walk(root string) *Walker { - info, err := os.Lstat(root) - return &Walker{stack: []item{{root, info, err}}} + return WalkFS(root, new(fs)) +} + +// WalkFS returns a new Walker rooted at root on the FileSystem fs. +func WalkFS(root string, fs FileSystem) *Walker { + info, err := fs.Lstat(root) + return &Walker{ + fs: fs, + stack: []item{{root, info, err}}, + } } // Step advances the Walker to the next file or directory, @@ -38,13 +45,13 @@ func Walk(root string) *Walker { // It returns false when the walk stops at the end of the tree. func (w *Walker) Step() bool { if w.descend && w.cur.err == nil && w.cur.info.IsDir() { - list, err := ioutil.ReadDir(w.cur.path) + list, err := w.fs.ReadDir(w.cur.path) if err != nil { w.cur.err = err w.stack = append(w.stack, w.cur) } else { for i := len(list) - 1; i >= 0; i-- { - path := filepath.Join(w.cur.path, list[i].Name()) + path := w.fs.Join(w.cur.path, list[i].Name()) w.stack = append(w.stack, item{path, list[i], nil}) } }