import "golang.org/x/tools/godoc/vfs"
Package vfs defines types for abstract file system access and provides an implementation accessing the file system of the underlying OS.
emptyvfs.go namespace.go os.go vfs.go
ReadFile reads the file named by path from fs and returns the contents.
type FileSystem interface { Opener Lstat(path string) (os.FileInfo, error) Stat(path string) (os.FileInfo, error) ReadDir(path string) ([]os.FileInfo, error) String() string }
The FileSystem interface specifies the methods godoc is using to access the file system for which it serves documentation.
func OS(root string) FileSystem
OS returns an implementation of FileSystem reading from the tree rooted at root. Recording a root is convenient everywhere but necessary on Windows, because the slash-separated path passed to Open has no way to specify a drive letter. Using a root lets code refer to OS(`c:\`), OS(`d:\`) and so on.
A NameSpace is a file system made up of other file systems mounted at specific locations in the name space.
The representation is a map from mount point locations to the list of file systems mounted at that location. A traditional Unix mount table would use a single file system per mount point, but we want to be able to mount multiple file systems on a single mount point and have the system behave as if the union of those file systems were present at the mount point. For example, if the OS file system has a Go installation in c:\Go and additional Go path trees in d:\Work1 and d:\Work2, then this name space creates the view we want for the godoc server:
NameSpace{ "/": { {old: "/", fs: OS(`c:\Go`), new: "/"}, }, "/src/pkg": { {old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"}, {old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"}, {old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"}, }, }
This is created by executing:
ns := NameSpace{} ns.Bind("/", OS(`c:\Go`), "/", BindReplace) ns.Bind("/src/pkg", OS(`d:\Work1`), "/src", BindAfter) ns.Bind("/src/pkg", OS(`d:\Work2`), "/src", BindAfter)
A particular mount point entry is a triple (old, fs, new), meaning that to operate on a path beginning with old, replace that prefix (old) with new and then pass that path to the FileSystem implementation fs.
If you do not explicitly mount a FileSystem at the root mountpoint "/" of the NameSpace like above, Stat("/") will return a "not found" error which could break typical directory traversal routines. In such cases, use NewNameSpace() to get a NameSpace pre-initialized with an emulated empty directory at root.
Given this name space, a ReadDir of /src/pkg/code will check each prefix of the path for a mount point (first /src/pkg/code, then /src/pkg, then /src, then /), stopping when it finds one. For the above example, /src/pkg/code will find the mount point at /src/pkg:
{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"}, {old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"}, {old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
ReadDir will when execute these three calls and merge the results:
OS(`c:\Go`).ReadDir("/src/pkg/code") OS(`d:\Work1').ReadDir("/src/code") OS(`d:\Work2').ReadDir("/src/code")
Note that the "/src/pkg" in "/src/pkg/code" has been replaced by just "/src" in the final two calls.
OS is itself an implementation of a file system: it implements OS(`c:\Go`).ReadDir("/src/pkg/code") as ioutil.ReadDir(`c:\Go\src\pkg\code`).
Because the new path is evaluated by fs (here OS(root)), another way to read the mount table is to mentally combine fs+new, so that this table:
{old: "/src/pkg", fs: OS(`c:\Go`), new: "/src/pkg"}, {old: "/src/pkg", fs: OS(`d:\Work1`), new: "/src"}, {old: "/src/pkg", fs: OS(`d:\Work2`), new: "/src"},
reads as:
"/src/pkg" -> c:\Go\src\pkg "/src/pkg" -> d:\Work1\src "/src/pkg" -> d:\Work2\src
An invariant (a redundancy) of the name space representation is that ns[mtpt][i].old is always equal to mtpt (in the example, ns["/src/pkg"]'s mount table entries always have old == "/src/pkg"). The 'old' field is useful to callers, because they receive just a []mountedFS and not any other indication of which mount point was found.
NewNameSpace returns a NameSpace pre-initialized with an empty emulated directory mounted on the root mount point "/". This allows directory traversal routines to work properly even if a folder is not explicitly mounted at root by the user.
Bind causes references to old to redirect to the path new in newfs. If mode is BindReplace, old redirections are discarded. If mode is BindBefore, this redirection takes priority over existing ones, but earlier ones are still consulted for paths that do not exist in newfs. If mode is BindAfter, this redirection happens only after existing ones have been tried and failed.
Fprint writes a text representation of the name space to w.
func (ns NameSpace) Open(path string) (ReadSeekCloser, error)
Open implements the FileSystem Open method.
ReadDir implements the FileSystem ReadDir method. It's where most of the magic is. (The rest is in resolve.)
Logically, ReadDir must return the union of all the directories that are named by path. In order to avoid misinterpreting Go packages, of all the directories that contain Go source code, we only include the files from the first, but we include subdirectories from all.
ReadDir must also return directory entries needed to reach mount points. If the name space looks like the example in the type NameSpace comment, but c:\Go does not have a src/pkg subdirectory, we still want to be able to find that subdirectory, because we've mounted d:\Work1 and d:\Work2 there. So if we don't see "src" in the directory listing for c:\Go, we add an entry for it before returning.
type Opener interface { Open(name string) (ReadSeekCloser, error) }
Opener is a minimal virtual filesystem that can only open regular files.
A ReadSeekCloser can Read, Seek, and Close.
Path | Synopsis |
---|---|
gatefs | Package gatefs provides an implementation of the FileSystem interface that wraps another FileSystem and limits its concurrency. |
httpfs | Package httpfs implements http.FileSystem using a godoc vfs.FileSystem. |
mapfs | Package mapfs file provides an implementation of the FileSystem interface based on the contents of a map[string]string. |
zipfs | Package zipfs file provides an implementation of the FileSystem interface based on the contents of a .zip file. |
Package vfs imports 9 packages (graph) and is imported by 79 packages. Updated 2 days ago. Refresh now. Tools for package owners.