// Walk walks the file tree rooted at root, calling walkFn for each file or // directory in the tree, including root. // // It requires only the fsi.FileSystem interface, and is therefore implementation independent. // // It is similar to filepath.Walk(root string, walkFunc) // // Directories are crawled in order of fs.ReadDir() // Walk crawls directories first, files second. // // Errors that arise visiting directories can be filtered by walkFn. // // Walk does not follow symbolic links. func Walk(fs fsi.FileSystem, root string, walkFn WalkFunc) error { info, err := fs.Lstat(root) if err != nil { // log.Printf("walk start error %10v %v", root, err) return walkFn(root, nil, err) } // log.Printf("walk start fnd %v", info.Name()) return walk(fs, root, info, walkFn) }
// walk recursively descends path, calling walkFn. func walk(fs fsi.FileSystem, path string, info os.FileInfo, walkFn WalkFunc) error { // cntr++ // if cntr > 20 { // return fmt.Errorf("too many recursions") // } err := walkFn(path, info, nil) if err != nil { if info.IsDir() && err == SkipDir { return nil } return err } if !info.IsDir() { return nil } fis, err := fs.ReadDir(path) // fnd := "" // for i := 0; i < len(fis); i++ { // fnd += fis[i].Name() + ", " // } // log.Printf("readdir of %-26v => %v, %v", path, len(fis), fnd) if err != nil && err != fsi.EmptyQueryResult { return walkFn(path, info, err) } // for _, fi := range fis { filename := pth.Join(path, pth.Base(fi.Name())) fileInfo, err := fs.Lstat(filename) if err != nil { if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir { return err } } else { err = walk(fs, filename, fileInfo, walkFn) if err != nil { if !fileInfo.IsDir() || err != SkipDir { return err } } } } return nil }
func CreateSys(fs fsi.FileSystem) (*bytes.Buffer, string) { bb := new(bytes.Buffer) wpf(bb, "--------create-dirs---------\n") fc1 := func(p []string) { path := pth.Join(p...) err := fs.MkdirAll(relOpt+path, os.ModePerm) if err != nil { wpf(bb, "MkdirAll failed %v\n", err) } } fc1([]string{"ch1"}) fc1([]string{"ch1", "ch2"}) fc1([]string{"ch1", "ch2", "ch3"}) fc1([]string{"ch1", "ch2", "ch3", "ch4"}) fc1([]string{"ch1", "ch2a"}) fc1([]string{"ch1A"}) fc1([]string{"ch1B"}) fc1([]string{"d1", "d2", "d3_secretdir", "neverwalked"}) fc1([]string{"d1", "d2", "d3a", "willwalk"}) wpf(bb, "\n--------retrieve-dirs---------\n") // retrieval gotByPath := 0 wntByPath := 5 fc2 := func(p []string) { path := pth.Join(p...) wpf(bb, "searching... %q\n", path) f, err := fs.Lstat(relOpt + path) if err != nil { wpf(bb, " nothing retrieved - err %v\n", err) } else { wpf(bb, " fnd %v \n", pth.Join(path, f.Name())) gotByPath++ } } fc2([]string{"ch1"}) fc2([]string{"ch1", "ch2"}) fc2([]string{"ch1", "non-exist-dir"}) fc2([]string{"ch1", "ch2", "ch3"}) fc2([]string{"ch1A"}) fc2([]string{rel}) wpf(bb, "\nfnd %v of %v dirs \n", gotByPath, wntByPath) wpf(bb, "\n-------create and save some files----\n") fc4a := func(name, content string) { err := fs.WriteFile(relOpt+name, []byte(content), os.ModePerm) if err != nil { wpf(bb, "WriteFile %v failed %v\n", name, err) } } fc4b := func(name, content string) { f, err := fs.Create(relOpt + name) if err != nil { wpf(bb, "Create %v failed %v\n", name, err) } if err != nil { return } _, err = f.WriteString(content) if err != nil { wpf(bb, "WriteString %v failed %v\n", name, err) } err = f.Close() if err != nil { wpf(bb, "Sync %v failed %v\n", name, err) } } fc4a("ch1/ch2/file_1", "content 1") fc4b("ch1/ch2/file_2", "content 2") fc4a("ch1/ch2/ch3/file3", "another content") fc4b(relPsep+"file4", "chq content 2") // fsc, ok := memfs.Unwrap(fs) // if ok { // fsc.Dump() // } // return bb, "" wpf(bb, "\n-------retrieve files again----\n\n") gotNumFiles := 0 wntNumFiles := 4 gotSizeFiles := 0 wntSizeFiles := 9 + 9 + 15 + 13 fc5 := func(path string) { files, err := fs.ReadDir(relOpt + path) if err != nil { wpf(bb, "filesByPath %v failed %v\n", path, err) } wpf(bb, " srch %-20q yielded %v dirs+files\n", relOpt+path, len(files)) for k, v := range files { if v.IsDir() { wpf(bb, " skip dir %v \n", v.Name()) continue } data, err := fs.ReadFile(pth.Join(path, v.Name())) if err != nil { wpf(bb, "could not get content of %v => %v\n", pth.Join(path, v.Name()), err) } wpf(bb, " %v - %v %s\n", k, pth.Join(path, v.Name()), data) gotNumFiles++ gotSizeFiles += len(data) } } fc5("ch1/ch2") fc5("ch1/ch2/ch3") fc5(rel) wpf(bb, "\n") wpf(bb, "fnd %2v of %2v fils \n", gotNumFiles, wntNumFiles) wpf(bb, "fnd %2v of %2v fsize \n", gotSizeFiles, wntSizeFiles) wpf(bb, "\n") testRes := "" if gotNumFiles != wntNumFiles { testRes += spf("Create files num : wnt %2v - got %v\n", wntNumFiles, gotNumFiles) } if gotSizeFiles != wntSizeFiles { testRes += spf("Create files size: wnt %2v - got %v\n", wntSizeFiles, gotSizeFiles) } return bb, testRes }