// IntersectInclude is not documented yet, please see TestIntersectInclude for // temporary usage details. // // TODO(rjeczalik): document func (c Control) IntersectInclude(src, dir string) map[string][]string { var ( old = c.FS spy = memfs.New() tee = Tee(old, spy) ) c.FS = tee dirs := c.Intersect(src, dir) c.FS = old switch len(dirs) { case 0: return nil case 1: return map[string][]string{dirs[0]: nil} } sort.StringSlice(dirs).Sort() m := make(map[string][]string, len(dirs)) for i := 1; i < len(dirs); i++ { m[dirs[i]] = nil j, n := strings.Index(dirs[i], dirs[i-1]), len(dirs[i-1]) if j == -1 || dirs[i][j+n] != os.PathSeparator { continue } for _, name := range (Control{FS: spy, Hidden: c.Hidden}).Readdirnames( filepath.Join(dir, dirs[i-1])) { if notindirs(dirs, name) { m[dirs[i-1]] = append(m[dirs[i-1]], filepath.Join(dirs[i-1], name)) } } } return m }
func TestRel(t *testing.T) { // To randomize. cases := map[string]struct{}{ "/": {}, "C:/": {}, "/a": {}, "X:/a": {}, "/tmp": {}, "C:/Windows/Temp": {}, "/private/var/tmp": {}, "C:/Program Files (x86)": {}, } for cas := range cases { cas = filepath.FromSlash(cas) for i, tree := range trees { // This is a hack, which emulates: // // func EqualFilesystem(lhs memfs.FS, rhs fs.FS) bool // // Which should probably hit memfs/util.go file eventually. exp, spy := move(tree, cas), memfs.New() if n := Copy(tree, Rel(spy, cas)); n == 0 { t.Errorf("want n!=0 (cas=%s, i=%d)", cas, i) continue } if !memfs.Equal(spy, exp) { t.Errorf("want spy=exp (cas=%s, i=%d)", cas, i) } return } } }
// TODO(rjeczalik): Split into TestTeeOpen and TestTeeReaddir func TestTeeOpen(t *testing.T) { cases := [...]struct { open []string read []string fs []byte }{ 0: { open: []string{"/w/x/y/z"}, fs: []byte(".\nw\n\tx\n\t\ty\n\t\t\tz/"), }, 1: { open: []string{"/a.txt", "/w/w.txt", "/a"}, fs: []byte(".\na/\na.txt\nw\n\tw.txt"), }, 2: { read: []string{"/a/b2/c1"}, fs: []byte(".\na\n\tb2\n\t\tc1\n\t\t\td1.txt\n\t\t\td2/\n\t\t\td3.txt"), }, 3: { read: []string{"/a/b1/c1", "/a/b1/c2", "/a/b1/c3"}, fs: []byte(".\na\n\tb1\n\t\tc1\n\t\t\tc1.txt\n\t\tc2\n\t\t\tc2.txt\n\t\t" + "c3\n\t\t\tc3.txt\n\t\t\td1/"), }, 4: { read: []string{"/w", "/w/x/y", "/w/x/y/z", "/w/x"}, fs: []byte(".\nw\n\tw.txt\n\tx\n\t\ty\n\t\t\tz\n\t\t\t\t1.txt\n\t\ty.txt"), }} Test: for i, cas := range cases { spy := memfs.New() tee := Tee(tree, spy) for j, path := range cas.open { if _, err := tee.Open(filepath.FromSlash(path)); err != nil { t.Errorf("want err=nil; got %q (i=%d, j=%d)", err, i, j) continue Test } } for j, path := range cas.read { f, err := tee.Open(filepath.FromSlash(path)) if err != nil { t.Errorf("want err=nil; got %q (i=%d, j=%d)", err, i, j) continue Test } if _, err = f.Readdir(0); err != nil { t.Errorf("want err=nil; got %q (i=%d, j=%d)", err, i, j) continue Test } } if !memfs.Equal(spy, memfs.Must(memfs.UnmarshalTab(cas.fs))) { t.Errorf("want Compare(...)=true; got false (i=%d)", i) } } }
func move(fs memfs.FS, off string) memfs.FS { mv := memfs.New() if err := mv.MkdirAll(off, 0xD); err != nil { panic(err) } if dirlen(mv.Tree) == 0 { return fs } dir, base := filepath.Split(off) tmp := memfs.Must(mv.Cd(dir)) tmp.Tree[base] = fs.Tree return mv }
func main() { if len(os.Args) == 2 && ishelp(os.Args[1]) { fmt.Println(usage) return } if len(flag.Args()) > 1 { die(usage) } var ( root = "." spy = memfs.New() printroot = true ) if len(flags.Args()) == 1 { root = flags.Args()[0] } if root == "." { root, _ = os.Getwd() printroot = false } root = filepath.Clean(root) (fsutil.Control{FS: fsutil.Tee(fs.FS{}, spy), Hidden: all}).Find(root, lvl) spy, err := spy.Cd(root) if err != nil { die(err) // TODO(rjeczalik): improve error message } if gowidth > 0 || varname != "" { if err = EncodeLiteral(spy, gowidth, varname, os.Stdout); err != nil { die(err) } } else { if err = gotree(root, printroot, spy, os.Stdout); err != nil { die(err) } } }
func TestCatchSpy(t *testing.T) { cases := [...]struct { depth int c Control dirs map[string][]string }{ 0: { 1, Control{FS: trees[3]}, map[string][]string{ filepath.FromSlash("/"): { "/1", "/1.txt", "/a.txt", "/abc", "/abc.txt", }, filepath.FromSlash("/1"): { "/1/2", "/1/2.txt", }, filepath.FromSlash("/abc"): { "/abc/1", "/abc/efg", "/abc/efg.txt", }, }, }, 1: { 1, Control{FS: trees[3], Hidden: true}, map[string][]string{ filepath.FromSlash("/"): { "/.1", "/.1.txt", "/.abc", "/.abc.txt", "/1", "/1.txt", "/a.txt", "/abc", "/abc.txt", }, filepath.FromSlash("/1"): { "/1/.2", "/1/.2.txt", "/1/2", "/1/2.txt", }, filepath.FromSlash("/abc"): { "/abc/.1", "/abc/.efg", "/abc/.efg.txt", "/abc/1", "/abc/efg", "/abc/efg.txt", }, }, }, 2: { 3, Control{FS: trees[3]}, map[string][]string{ filepath.FromSlash("/abc/1"): { "/abc/1/2", "/abc/1/2/3", "/abc/1/2/3/txt", "/abc/1/2/3.txt", "/abc/1/2.txt", }, filepath.FromSlash("/1"): { "/1/2", "/1/2/3", "/1/2/3/txt", "/1/2/3.txt", "/1/2.txt", }, filepath.FromSlash("/abc"): { "/abc/1", "/abc/1/2", "/abc/1/2/3", "/abc/1/2/3.txt", "/abc/1/2.txt", "/abc/efg", "/abc/efg/hij", "/abc/efg/hij/txt", "/abc/efg/hij.txt", "/abc/efg.txt", }, }, }, } for i, cas := range cases { for dir, v := range cas.dirs { spy := memfs.New() for j, fs := range []fs.Filesystem{ 0: cas.c.FS, 1: Tee(cas.c.FS, spy), 2: spy, } { c := cas.c c.FS = fs found := c.Find(dir, cas.depth) if found == nil { t.Errorf("want found!=nil (i=%d, dir=%s, j=%d)", i, dir, j) continue } if !equal(found, v) { t.Errorf("want found=%v; got %v (i=%d, dir=%s, j=%d)", v, found, i, dir, j) } } found := (Control{FS: spy, Hidden: true}).Find(dir, cas.depth) if found == nil { t.Errorf("want found!=nil (i=%d, dir=%s)", i, dir) continue } if !equal(found, v) { t.Errorf("want found=%v; got %v (i=%d, dir=%s)", v, found, i, dir) } } } }