Add FileSystem and WalkFS
Closes #1
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 @@
// 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 @@
// 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 @@
// 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})
}
}