func TestNewNameSpace(t *testing.T) { // We will mount this filesystem under /fs1 mount := mapfs.New(map[string]string{"fs1file": "abcdefgh"}) // Existing process. This should give error on Stat("/") t1 := vfs.NameSpace{} t1.Bind("/fs1", mount, "/", vfs.BindReplace) // using NewNameSpace. This should work fine. t2 := emptyvfs.NewNameSpace() t2.Bind("/fs1", mount, "/", vfs.BindReplace) testcases := map[string][]bool{ "/": []bool{false, true}, "/fs1": []bool{true, true}, "/fs1/fs1file": []bool{true, true}, } fss := []vfs.FileSystem{t1, t2} for j, fs := range fss { for k, v := range testcases { _, err := fs.Stat(k) result := err == nil if result != v[j] { t.Errorf("fs: %d, testcase: %s, want: %v, got: %v, err: %s", j, k, v[j], result, err) } } } }
// Union returns a new FileSystem which is the union of the provided file systems. // For read operations, vfs.NameSpace is used and its behavior is inherited. // Write operations are applied to the first file system which contains the parent directory. // The union file system is not thread-safe. Concurrent access to itself and/or // its underlying file systems requires synchronization. func Union(fileSystems ...FileSystem) FileSystem { if len(fileSystems) == 0 { return ReadOnly(Map(nil)) } if len(fileSystems) == 1 { return fileSystems[0] } ns := vfs.NameSpace{} for _, fs := range fileSystems { ns.Bind("/", fs, "/", vfs.BindAfter) } return &unionFS{ NameSpace: ns, fileSystems: fileSystems, } }
// paths determines the paths to use. // // If we are passed an operating system path like . or ./foo or /foo/bar or c:\mysrc, // we need to map that path somewhere in the fs name space so that routines // like getPageInfo will see it. We use the arbitrarily-chosen virtual path "/target" // for this. That is, if we get passed a directory like the above, we map that // directory so that getPageInfo sees it as /target. // Returns the absolute and relative paths. func paths(fs vfs.NameSpace, pres *Presentation, path string) (string, string) { if filepath.IsAbs(path) { fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace) return target, target } if build.IsLocalImport(path) { cwd, _ := os.Getwd() // ignore errors path = filepath.Join(cwd, path) fs.Bind(target, vfs.OS(path), "/", vfs.BindReplace) return target, target } if bp, _ := build.Import(path, "", build.FindOnly); bp.Dir != "" && bp.ImportPath != "" { fs.Bind(target, vfs.OS(bp.Dir), "/", vfs.BindReplace) return target, bp.ImportPath } return pathpkg.Join(pres.PkgFSRoot(), path), path }
// NewNameSpace returns a vfs.NameSpace initialized with an empty // emulated directory mounted on the root mount point "/" so that // directory traversal routines don't break if the user doesn't // explicitly mount a FileSystem at "/". See the following issue: // https://github.com/golang/go/issues/14190 func NewNameSpace() vfs.NameSpace { ns := vfs.NameSpace{} ns.Bind("/", newemptyVFS(), "/", vfs.BindReplace) return ns }
func (p *localTranslater) fileExists(fs vfs.NameSpace, name string) bool { if fi, err := fs.Stat(name); err != nil || fi.IsDir() { return false } return true }