webdav: define property system and implement PROPFIND.
This change adds support for PROPFIND requests to net/webdav.
It contains a proposed PropSystem interface and a preliminary
implementation of an in-memory property system. As discussed
with nigeltao, this is the first of approximately 4-5 CLs to
get property support in the net/webdav package.
Current coverage of litmus 'props' test suite:
16 tests were skipped, 14 tests run. 10 passed, 4 failed. 71.4%
Change-Id: I0bc5f375422137e911a2f6fb0e99c43a5a52d5ac
Reviewed-on: https://go-review.googlesource.com/3417
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/webdav/file.go b/webdav/file.go
index aa4ea6a..2f62dc4 100644
--- a/webdav/file.go
+++ b/webdav/file.go
@@ -672,3 +672,54 @@
}
return http.StatusNoContent, nil
}
+
+// walkFS traverses filesystem fs starting at path up to depth levels.
+//
+// Allowed values for depth are 0, 1 or infiniteDepth. For each visited node,
+// walkFS calls walkFn. If a visited file system node is a directory and
+// walkFn returns filepath.SkipDir, walkFS will skip traversal of this node.
+func walkFS(fs FileSystem, depth int, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
+ // This implementation is based on Walk's code in the standard path/filepath package.
+ err := walkFn(path, info, nil)
+ if err != nil {
+ if info.IsDir() && err == filepath.SkipDir {
+ return nil
+ }
+ return err
+ }
+ if !info.IsDir() || depth == 0 {
+ return nil
+ }
+ if depth == 1 {
+ depth = 0
+ }
+
+ // Read directory names.
+ f, err := fs.OpenFile(path, os.O_RDONLY, 0)
+ if err != nil {
+ return walkFn(path, info, err)
+ }
+ fileInfos, err := f.Readdir(0)
+ f.Close()
+ if err != nil {
+ return walkFn(path, info, err)
+ }
+
+ for _, fileInfo := range fileInfos {
+ filename := filepath.Join(path, fileInfo.Name())
+ fileInfo, err := fs.Stat(filename)
+ if err != nil {
+ if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
+ return err
+ }
+ } else {
+ err = walkFS(fs, depth, filename, fileInfo, walkFn)
+ if err != nil {
+ if !fileInfo.IsDir() || err != filepath.SkipDir {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}