aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/path/path.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/path/path.go')
-rw-r--r--src/pkg/path/path.go54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/pkg/path/path.go b/src/pkg/path/path.go
index 7fa8b863ba..97245213ea 100644
--- a/src/pkg/path/path.go
+++ b/src/pkg/path/path.go
@@ -6,7 +6,11 @@
// slash-separated filename paths.
package path
-import "strings"
+import (
+ "io";
+ "os";
+ "strings";
+)
// Clean returns the shortest path name equivalent to path
// by purely lexical processing. It applies the following rules
@@ -132,3 +136,51 @@ func Ext(path string) string {
}
return "";
}
+
+// Visitor methods are invoked for corresponding file tree entries
+// visited by Walk. The parameter path is the full path of d relative
+// to root.
+type Visitor interface {
+ VisitDir(path string, d *os.Dir) bool;
+ VisitFile(path string, d *os.Dir);
+}
+
+func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
+ if !d.IsDirectory() {
+ v.VisitFile(path, d);
+ return;
+ }
+
+ if !v.VisitDir(path, d) {
+ return; // skip directory entries
+ }
+
+ list, err := io.ReadDir(path);
+ if err != nil {
+ if errors != nil {
+ errors <- err;
+ }
+ }
+
+ for _, e := range list {
+ walk(Join(path, e.Name), e, v, errors);
+ }
+}
+
+// Walk walks the file tree rooted at root, calling v.VisitDir or
+// v.VisitFile for each directory or file in the tree, including root.
+// If v.VisitDir returns false, Walk skips the directory's entries;
+// otherwise it invokes itself for each directory entry in sorted order.
+// An error reading a directory does not abort the Walk.
+// If errors != nil, Walk sends each directory read error
+// to the channel. Otherwise Walk discards the error.
+func Walk(root string, v Visitor, errors chan<- os.Error) {
+ d, err := os.Lstat(root);
+ if err != nil {
+ if errors != nil {
+ errors <- err;
+ }
+ return; // can't progress
+ }
+ walk(root, d, v, errors);
+}