Add generated file
This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
89
vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go
generated
vendored
Normal file
89
vendor/golang.org/x/tools/godoc/vfs/emptyvfs.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 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.
|
||||
func NewNameSpace() NameSpace {
|
||||
ns := NameSpace{}
|
||||
ns.Bind("/", &emptyVFS{}, "/", BindReplace)
|
||||
return ns
|
||||
}
|
||||
|
||||
// type emptyVFS emulates a FileSystem consisting of an empty directory
|
||||
type emptyVFS struct{}
|
||||
|
||||
// Open implements Opener. Since emptyVFS is an empty directory, all
|
||||
// attempts to open a file should returns errors.
|
||||
func (e *emptyVFS) Open(path string) (ReadSeekCloser, error) {
|
||||
if path == "/" {
|
||||
return nil, fmt.Errorf("open: / is a directory")
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
// Stat returns os.FileInfo for an empty directory if the path is
|
||||
// is root "/" or error. os.FileInfo is implemented by emptyVFS
|
||||
func (e *emptyVFS) Stat(path string) (os.FileInfo, error) {
|
||||
if path == "/" {
|
||||
return e, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func (e *emptyVFS) Lstat(path string) (os.FileInfo, error) {
|
||||
return e.Stat(path)
|
||||
}
|
||||
|
||||
// ReadDir returns an empty os.FileInfo slice for "/", else error.
|
||||
func (e *emptyVFS) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
if path == "/" {
|
||||
return []os.FileInfo{}, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func (e *emptyVFS) String() string {
|
||||
return "emptyVFS(/)"
|
||||
}
|
||||
|
||||
func (e *emptyVFS) RootType(path string) RootType {
|
||||
return ""
|
||||
}
|
||||
|
||||
// These functions below implement os.FileInfo for the single
|
||||
// empty emulated directory.
|
||||
|
||||
func (e *emptyVFS) Name() string {
|
||||
return "/"
|
||||
}
|
||||
|
||||
func (e *emptyVFS) Size() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *emptyVFS) Mode() os.FileMode {
|
||||
return os.ModeDir | os.ModePerm
|
||||
}
|
||||
|
||||
func (e *emptyVFS) ModTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (e *emptyVFS) IsDir() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (e *emptyVFS) Sys() interface{} {
|
||||
return nil
|
||||
}
|
58
vendor/golang.org/x/tools/godoc/vfs/emptyvfs_test.go
generated
vendored
Normal file
58
vendor/golang.org/x/tools/godoc/vfs/emptyvfs_test.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vfs_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
"golang.org/x/tools/godoc/vfs/mapfs"
|
||||
)
|
||||
|
||||
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 := vfs.NewNameSpace()
|
||||
t2.Bind("/fs1", mount, "/", vfs.BindReplace)
|
||||
|
||||
testcases := map[string][]bool{
|
||||
"/": {false, true},
|
||||
"/fs1": {true, true},
|
||||
"/fs1/fs1file": {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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fi, err := t2.Stat("/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if fi.Name() != "/" {
|
||||
t.Errorf("t2.Name() : want:%s got:%s", "/", fi.Name())
|
||||
}
|
||||
|
||||
if !fi.ModTime().IsZero() {
|
||||
t.Errorf("t2.Modime() : want:%v got:%v", time.Time{}, fi.ModTime())
|
||||
}
|
||||
}
|
93
vendor/golang.org/x/tools/godoc/vfs/gatefs/gatefs.go
generated
vendored
Normal file
93
vendor/golang.org/x/tools/godoc/vfs/gatefs/gatefs.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package gatefs provides an implementation of the FileSystem
|
||||
// interface that wraps another FileSystem and limits its concurrency.
|
||||
package gatefs // import "golang.org/x/tools/godoc/vfs/gatefs"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
// New returns a new FileSystem that delegates to fs.
|
||||
// If gateCh is non-nil and buffered, it's used as a gate
|
||||
// to limit concurrency on calls to fs.
|
||||
func New(fs vfs.FileSystem, gateCh chan bool) vfs.FileSystem {
|
||||
if cap(gateCh) == 0 {
|
||||
return fs
|
||||
}
|
||||
return gatefs{fs, gate(gateCh)}
|
||||
}
|
||||
|
||||
type gate chan bool
|
||||
|
||||
func (g gate) enter() { g <- true }
|
||||
func (g gate) leave() { <-g }
|
||||
|
||||
type gatefs struct {
|
||||
fs vfs.FileSystem
|
||||
gate
|
||||
}
|
||||
|
||||
func (fs gatefs) String() string {
|
||||
return fmt.Sprintf("gated(%s, %d)", fs.fs.String(), cap(fs.gate))
|
||||
}
|
||||
|
||||
func (fs gatefs) RootType(path string) vfs.RootType {
|
||||
return fs.fs.RootType(path)
|
||||
}
|
||||
|
||||
func (fs gatefs) Open(p string) (vfs.ReadSeekCloser, error) {
|
||||
fs.enter()
|
||||
defer fs.leave()
|
||||
rsc, err := fs.fs.Open(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gatef{rsc, fs.gate}, nil
|
||||
}
|
||||
|
||||
func (fs gatefs) Lstat(p string) (os.FileInfo, error) {
|
||||
fs.enter()
|
||||
defer fs.leave()
|
||||
return fs.fs.Lstat(p)
|
||||
}
|
||||
|
||||
func (fs gatefs) Stat(p string) (os.FileInfo, error) {
|
||||
fs.enter()
|
||||
defer fs.leave()
|
||||
return fs.fs.Stat(p)
|
||||
}
|
||||
|
||||
func (fs gatefs) ReadDir(p string) ([]os.FileInfo, error) {
|
||||
fs.enter()
|
||||
defer fs.leave()
|
||||
return fs.fs.ReadDir(p)
|
||||
}
|
||||
|
||||
type gatef struct {
|
||||
rsc vfs.ReadSeekCloser
|
||||
gate
|
||||
}
|
||||
|
||||
func (f gatef) Read(p []byte) (n int, err error) {
|
||||
f.enter()
|
||||
defer f.leave()
|
||||
return f.rsc.Read(p)
|
||||
}
|
||||
|
||||
func (f gatef) Seek(offset int64, whence int) (ret int64, err error) {
|
||||
f.enter()
|
||||
defer f.leave()
|
||||
return f.rsc.Seek(offset, whence)
|
||||
}
|
||||
|
||||
func (f gatef) Close() error {
|
||||
f.enter()
|
||||
defer f.leave()
|
||||
return f.rsc.Close()
|
||||
}
|
39
vendor/golang.org/x/tools/godoc/vfs/gatefs/gatefs_test.go
generated
vendored
Normal file
39
vendor/golang.org/x/tools/godoc/vfs/gatefs/gatefs_test.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gatefs_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
"golang.org/x/tools/godoc/vfs/gatefs"
|
||||
)
|
||||
|
||||
func TestRootType(t *testing.T) {
|
||||
goPath := os.Getenv("GOPATH")
|
||||
var expectedType vfs.RootType
|
||||
if goPath == "" {
|
||||
expectedType = ""
|
||||
} else {
|
||||
expectedType = vfs.RootTypeGoPath
|
||||
}
|
||||
tests := []struct {
|
||||
path string
|
||||
fsType vfs.RootType
|
||||
}{
|
||||
{runtime.GOROOT(), vfs.RootTypeGoRoot},
|
||||
{goPath, expectedType},
|
||||
{"/tmp/", ""},
|
||||
}
|
||||
|
||||
for _, item := range tests {
|
||||
fs := gatefs.New(vfs.OS(item.path), make(chan bool, 1))
|
||||
if fs.RootType("path") != item.fsType {
|
||||
t.Errorf("unexpected fsType. Expected- %v, Got- %v", item.fsType, fs.RootType("path"))
|
||||
}
|
||||
}
|
||||
}
|
94
vendor/golang.org/x/tools/godoc/vfs/httpfs/httpfs.go
generated
vendored
Normal file
94
vendor/golang.org/x/tools/godoc/vfs/httpfs/httpfs.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package httpfs implements http.FileSystem using a godoc vfs.FileSystem.
|
||||
package httpfs // import "golang.org/x/tools/godoc/vfs/httpfs"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
func New(fs vfs.FileSystem) http.FileSystem {
|
||||
return &httpFS{fs}
|
||||
}
|
||||
|
||||
type httpFS struct {
|
||||
fs vfs.FileSystem
|
||||
}
|
||||
|
||||
func (h *httpFS) Open(name string) (http.File, error) {
|
||||
fi, err := h.fs.Stat(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return &httpDir{h.fs, name, nil}, nil
|
||||
}
|
||||
f, err := h.fs.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &httpFile{h.fs, f, name}, nil
|
||||
}
|
||||
|
||||
// httpDir implements http.File for a directory in a FileSystem.
|
||||
type httpDir struct {
|
||||
fs vfs.FileSystem
|
||||
name string
|
||||
pending []os.FileInfo
|
||||
}
|
||||
|
||||
func (h *httpDir) Close() error { return nil }
|
||||
func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
|
||||
func (h *httpDir) Read([]byte) (int, error) {
|
||||
return 0, fmt.Errorf("cannot Read from directory %s", h.name)
|
||||
}
|
||||
|
||||
func (h *httpDir) Seek(offset int64, whence int) (int64, error) {
|
||||
if offset == 0 && whence == 0 {
|
||||
h.pending = nil
|
||||
return 0, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported Seek in directory %s", h.name)
|
||||
}
|
||||
|
||||
func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if h.pending == nil {
|
||||
d, err := h.fs.ReadDir(h.name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d == nil {
|
||||
d = []os.FileInfo{} // not nil
|
||||
}
|
||||
h.pending = d
|
||||
}
|
||||
|
||||
if len(h.pending) == 0 && count > 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
if count <= 0 || count > len(h.pending) {
|
||||
count = len(h.pending)
|
||||
}
|
||||
d := h.pending[:count]
|
||||
h.pending = h.pending[count:]
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// httpFile implements http.File for a file (not directory) in a FileSystem.
|
||||
type httpFile struct {
|
||||
fs vfs.FileSystem
|
||||
vfs.ReadSeekCloser
|
||||
name string
|
||||
}
|
||||
|
||||
func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
|
||||
func (h *httpFile) Readdir(int) ([]os.FileInfo, error) {
|
||||
return nil, fmt.Errorf("cannot Readdir from file %s", h.name)
|
||||
}
|
156
vendor/golang.org/x/tools/godoc/vfs/mapfs/mapfs.go
generated
vendored
Normal file
156
vendor/golang.org/x/tools/godoc/vfs/mapfs/mapfs.go
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package mapfs file provides an implementation of the FileSystem
|
||||
// interface based on the contents of a map[string]string.
|
||||
package mapfs // import "golang.org/x/tools/godoc/vfs/mapfs"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
pathpkg "path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
// New returns a new FileSystem from the provided map.
|
||||
// Map keys should be forward slash-separated pathnames
|
||||
// and not contain a leading slash.
|
||||
func New(m map[string]string) vfs.FileSystem {
|
||||
return mapFS(m)
|
||||
}
|
||||
|
||||
// mapFS is the map based implementation of FileSystem
|
||||
type mapFS map[string]string
|
||||
|
||||
func (fs mapFS) String() string { return "mapfs" }
|
||||
|
||||
func (fs mapFS) RootType(p string) vfs.RootType {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (fs mapFS) Close() error { return nil }
|
||||
|
||||
func filename(p string) string {
|
||||
return strings.TrimPrefix(p, "/")
|
||||
}
|
||||
|
||||
func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
|
||||
b, ok := fs[filename(p)]
|
||||
if !ok {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return nopCloser{strings.NewReader(b)}, nil
|
||||
}
|
||||
|
||||
func fileInfo(name, contents string) os.FileInfo {
|
||||
return mapFI{name: pathpkg.Base(name), size: len(contents)}
|
||||
}
|
||||
|
||||
func dirInfo(name string) os.FileInfo {
|
||||
return mapFI{name: pathpkg.Base(name), dir: true}
|
||||
}
|
||||
|
||||
func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
|
||||
b, ok := fs[filename(p)]
|
||||
if ok {
|
||||
return fileInfo(p, b), nil
|
||||
}
|
||||
ents, _ := fs.ReadDir(p)
|
||||
if len(ents) > 0 {
|
||||
return dirInfo(p), nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
func (fs mapFS) Stat(p string) (os.FileInfo, error) {
|
||||
return fs.Lstat(p)
|
||||
}
|
||||
|
||||
// slashdir returns path.Dir(p), but special-cases paths not beginning
|
||||
// with a slash to be in the root.
|
||||
func slashdir(p string) string {
|
||||
d := pathpkg.Dir(p)
|
||||
if d == "." {
|
||||
return "/"
|
||||
}
|
||||
if strings.HasPrefix(p, "/") {
|
||||
return d
|
||||
}
|
||||
return "/" + d
|
||||
}
|
||||
|
||||
func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
|
||||
p = pathpkg.Clean(p)
|
||||
var ents []string
|
||||
fim := make(map[string]os.FileInfo) // base -> fi
|
||||
for fn, b := range fs {
|
||||
dir := slashdir(fn)
|
||||
isFile := true
|
||||
var lastBase string
|
||||
for {
|
||||
if dir == p {
|
||||
base := lastBase
|
||||
if isFile {
|
||||
base = pathpkg.Base(fn)
|
||||
}
|
||||
if fim[base] == nil {
|
||||
var fi os.FileInfo
|
||||
if isFile {
|
||||
fi = fileInfo(fn, b)
|
||||
} else {
|
||||
fi = dirInfo(base)
|
||||
}
|
||||
ents = append(ents, base)
|
||||
fim[base] = fi
|
||||
}
|
||||
}
|
||||
if dir == "/" {
|
||||
break
|
||||
} else {
|
||||
isFile = false
|
||||
lastBase = pathpkg.Base(dir)
|
||||
dir = pathpkg.Dir(dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ents) == 0 {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
sort.Strings(ents)
|
||||
var list []os.FileInfo
|
||||
for _, dir := range ents {
|
||||
list = append(list, fim[dir])
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// mapFI is the map-based implementation of FileInfo.
|
||||
type mapFI struct {
|
||||
name string
|
||||
size int
|
||||
dir bool
|
||||
}
|
||||
|
||||
func (fi mapFI) IsDir() bool { return fi.dir }
|
||||
func (fi mapFI) ModTime() time.Time { return time.Time{} }
|
||||
func (fi mapFI) Mode() os.FileMode {
|
||||
if fi.IsDir() {
|
||||
return 0755 | os.ModeDir
|
||||
}
|
||||
return 0444
|
||||
}
|
||||
func (fi mapFI) Name() string { return pathpkg.Base(fi.name) }
|
||||
func (fi mapFI) Size() int64 { return int64(fi.size) }
|
||||
func (fi mapFI) Sys() interface{} { return nil }
|
||||
|
||||
type nopCloser struct {
|
||||
io.ReadSeeker
|
||||
}
|
||||
|
||||
func (nc nopCloser) Close() error { return nil }
|
111
vendor/golang.org/x/tools/godoc/vfs/mapfs/mapfs_test.go
generated
vendored
Normal file
111
vendor/golang.org/x/tools/godoc/vfs/mapfs/mapfs_test.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mapfs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOpenRoot(t *testing.T) {
|
||||
fs := New(map[string]string{
|
||||
"foo/bar/three.txt": "a",
|
||||
"foo/bar.txt": "b",
|
||||
"top.txt": "c",
|
||||
"other-top.txt": "d",
|
||||
})
|
||||
tests := []struct {
|
||||
path string
|
||||
want string
|
||||
}{
|
||||
{"/foo/bar/three.txt", "a"},
|
||||
{"foo/bar/three.txt", "a"},
|
||||
{"foo/bar.txt", "b"},
|
||||
{"top.txt", "c"},
|
||||
{"/top.txt", "c"},
|
||||
{"other-top.txt", "d"},
|
||||
{"/other-top.txt", "d"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
rsc, err := fs.Open(tt.path)
|
||||
if err != nil {
|
||||
t.Errorf("Open(%q) = %v", tt.path, err)
|
||||
continue
|
||||
}
|
||||
slurp, err := ioutil.ReadAll(rsc)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(slurp) != tt.want {
|
||||
t.Errorf("Read(%q) = %q; want %q", tt.path, tt.want, slurp)
|
||||
}
|
||||
rsc.Close()
|
||||
}
|
||||
|
||||
_, err := fs.Open("/xxxx")
|
||||
if !os.IsNotExist(err) {
|
||||
t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaddir(t *testing.T) {
|
||||
fs := New(map[string]string{
|
||||
"foo/bar/three.txt": "333",
|
||||
"foo/bar.txt": "22",
|
||||
"top.txt": "top.txt file",
|
||||
"other-top.txt": "other-top.txt file",
|
||||
})
|
||||
tests := []struct {
|
||||
dir string
|
||||
want []os.FileInfo
|
||||
}{
|
||||
{
|
||||
dir: "/",
|
||||
want: []os.FileInfo{
|
||||
mapFI{name: "foo", dir: true},
|
||||
mapFI{name: "other-top.txt", size: len("other-top.txt file")},
|
||||
mapFI{name: "top.txt", size: len("top.txt file")},
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: "/foo",
|
||||
want: []os.FileInfo{
|
||||
mapFI{name: "bar", dir: true},
|
||||
mapFI{name: "bar.txt", size: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: "/foo/",
|
||||
want: []os.FileInfo{
|
||||
mapFI{name: "bar", dir: true},
|
||||
mapFI{name: "bar.txt", size: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
dir: "/foo/bar",
|
||||
want: []os.FileInfo{
|
||||
mapFI{name: "three.txt", size: 3},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
fis, err := fs.ReadDir(tt.dir)
|
||||
if err != nil {
|
||||
t.Errorf("ReadDir(%q) = %v", tt.dir, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(fis, tt.want) {
|
||||
t.Errorf("ReadDir(%q) = %#v; want %#v", tt.dir, fis, tt.want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
_, err := fs.ReadDir("/xxxx")
|
||||
if !os.IsNotExist(err) {
|
||||
t.Errorf("ReadDir /xxxx = %v; want os.IsNotExist error", err)
|
||||
}
|
||||
}
|
403
vendor/golang.org/x/tools/godoc/vfs/namespace.go
generated
vendored
Normal file
403
vendor/golang.org/x/tools/godoc/vfs/namespace.go
generated
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
pathpkg "path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Setting debugNS = true will enable debugging prints about
|
||||
// name space translations.
|
||||
const debugNS = false
|
||||
|
||||
// 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.
|
||||
//
|
||||
type NameSpace map[string][]mountedFS
|
||||
|
||||
// A mountedFS handles requests for path by replacing
|
||||
// a prefix 'old' with 'new' and then calling the fs methods.
|
||||
type mountedFS struct {
|
||||
old string
|
||||
fs FileSystem
|
||||
new string
|
||||
}
|
||||
|
||||
// hasPathPrefix returns true if x == y or x == y + "/" + more
|
||||
func hasPathPrefix(x, y string) bool {
|
||||
return x == y || strings.HasPrefix(x, y) && (strings.HasSuffix(y, "/") || strings.HasPrefix(x[len(y):], "/"))
|
||||
}
|
||||
|
||||
// translate translates path for use in m, replacing old with new.
|
||||
//
|
||||
// mountedFS{"/src/pkg", fs, "/src"}.translate("/src/pkg/code") == "/src/code".
|
||||
func (m mountedFS) translate(path string) string {
|
||||
path = pathpkg.Clean("/" + path)
|
||||
if !hasPathPrefix(path, m.old) {
|
||||
panic("translate " + path + " but old=" + m.old)
|
||||
}
|
||||
return pathpkg.Join(m.new, path[len(m.old):])
|
||||
}
|
||||
|
||||
func (NameSpace) String() string {
|
||||
return "ns"
|
||||
}
|
||||
|
||||
// Fprint writes a text representation of the name space to w.
|
||||
func (ns NameSpace) Fprint(w io.Writer) {
|
||||
fmt.Fprint(w, "name space {\n")
|
||||
var all []string
|
||||
for mtpt := range ns {
|
||||
all = append(all, mtpt)
|
||||
}
|
||||
sort.Strings(all)
|
||||
for _, mtpt := range all {
|
||||
fmt.Fprintf(w, "\t%s:\n", mtpt)
|
||||
for _, m := range ns[mtpt] {
|
||||
fmt.Fprintf(w, "\t\t%s %s\n", m.fs, m.new)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "}\n")
|
||||
}
|
||||
|
||||
// clean returns a cleaned, rooted path for evaluation.
|
||||
// It canonicalizes the path so that we can use string operations
|
||||
// to analyze it.
|
||||
func (NameSpace) clean(path string) string {
|
||||
return pathpkg.Clean("/" + path)
|
||||
}
|
||||
|
||||
type BindMode int
|
||||
|
||||
const (
|
||||
BindReplace BindMode = iota
|
||||
BindBefore
|
||||
BindAfter
|
||||
)
|
||||
|
||||
// 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.
|
||||
func (ns NameSpace) Bind(old string, newfs FileSystem, new string, mode BindMode) {
|
||||
old = ns.clean(old)
|
||||
new = ns.clean(new)
|
||||
m := mountedFS{old, newfs, new}
|
||||
var mtpt []mountedFS
|
||||
switch mode {
|
||||
case BindReplace:
|
||||
mtpt = append(mtpt, m)
|
||||
case BindAfter:
|
||||
mtpt = append(mtpt, ns.resolve(old)...)
|
||||
mtpt = append(mtpt, m)
|
||||
case BindBefore:
|
||||
mtpt = append(mtpt, m)
|
||||
mtpt = append(mtpt, ns.resolve(old)...)
|
||||
}
|
||||
|
||||
// Extend m.old, m.new in inherited mount point entries.
|
||||
for i := range mtpt {
|
||||
m := &mtpt[i]
|
||||
if m.old != old {
|
||||
if !hasPathPrefix(old, m.old) {
|
||||
// This should not happen. If it does, panic so
|
||||
// that we can see the call trace that led to it.
|
||||
panic(fmt.Sprintf("invalid Bind: old=%q m={%q, %s, %q}", old, m.old, m.fs.String(), m.new))
|
||||
}
|
||||
suffix := old[len(m.old):]
|
||||
m.old = pathpkg.Join(m.old, suffix)
|
||||
m.new = pathpkg.Join(m.new, suffix)
|
||||
}
|
||||
}
|
||||
|
||||
ns[old] = mtpt
|
||||
}
|
||||
|
||||
// resolve resolves a path to the list of mountedFS to use for path.
|
||||
func (ns NameSpace) resolve(path string) []mountedFS {
|
||||
path = ns.clean(path)
|
||||
for {
|
||||
if m := ns[path]; m != nil {
|
||||
if debugNS {
|
||||
fmt.Printf("resolve %s: %v\n", path, m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
if path == "/" {
|
||||
break
|
||||
}
|
||||
path = pathpkg.Dir(path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open implements the FileSystem Open method.
|
||||
func (ns NameSpace) Open(path string) (ReadSeekCloser, error) {
|
||||
var err error
|
||||
for _, m := range ns.resolve(path) {
|
||||
if debugNS {
|
||||
fmt.Printf("tx %s: %v\n", path, m.translate(path))
|
||||
}
|
||||
tp := m.translate(path)
|
||||
r, err1 := m.fs.Open(tp)
|
||||
if err1 == nil {
|
||||
return r, nil
|
||||
}
|
||||
// IsNotExist errors in overlay FSes can mask real errors in
|
||||
// the underlying FS, so ignore them if there is another error.
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
err = err1
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// stat implements the FileSystem Stat and Lstat methods.
|
||||
func (ns NameSpace) stat(path string, f func(FileSystem, string) (os.FileInfo, error)) (os.FileInfo, error) {
|
||||
var err error
|
||||
for _, m := range ns.resolve(path) {
|
||||
fi, err1 := f(m.fs, m.translate(path))
|
||||
if err1 == nil {
|
||||
return fi, nil
|
||||
}
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = &os.PathError{Op: "stat", Path: path, Err: os.ErrNotExist}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (ns NameSpace) Stat(path string) (os.FileInfo, error) {
|
||||
return ns.stat(path, FileSystem.Stat)
|
||||
}
|
||||
|
||||
func (ns NameSpace) Lstat(path string) (os.FileInfo, error) {
|
||||
return ns.stat(path, FileSystem.Lstat)
|
||||
}
|
||||
|
||||
// dirInfo is a trivial implementation of os.FileInfo for a directory.
|
||||
type dirInfo string
|
||||
|
||||
func (d dirInfo) Name() string { return string(d) }
|
||||
func (d dirInfo) Size() int64 { return 0 }
|
||||
func (d dirInfo) Mode() os.FileMode { return os.ModeDir | 0555 }
|
||||
func (d dirInfo) ModTime() time.Time { return startTime }
|
||||
func (d dirInfo) IsDir() bool { return true }
|
||||
func (d dirInfo) Sys() interface{} { return nil }
|
||||
|
||||
var startTime = time.Now()
|
||||
|
||||
// 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.
|
||||
//
|
||||
func (ns NameSpace) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
path = ns.clean(path)
|
||||
|
||||
var (
|
||||
haveGo = false
|
||||
haveName = map[string]bool{}
|
||||
all []os.FileInfo
|
||||
err error
|
||||
first []os.FileInfo
|
||||
)
|
||||
|
||||
for _, m := range ns.resolve(path) {
|
||||
dir, err1 := m.fs.ReadDir(m.translate(path))
|
||||
if err1 != nil {
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if dir == nil {
|
||||
dir = []os.FileInfo{}
|
||||
}
|
||||
|
||||
if first == nil {
|
||||
first = dir
|
||||
}
|
||||
|
||||
// If we don't yet have Go files in 'all' and this directory
|
||||
// has some, add all the files from this directory.
|
||||
// Otherwise, only add subdirectories.
|
||||
useFiles := false
|
||||
if !haveGo {
|
||||
for _, d := range dir {
|
||||
if strings.HasSuffix(d.Name(), ".go") {
|
||||
useFiles = true
|
||||
haveGo = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range dir {
|
||||
name := d.Name()
|
||||
if (d.IsDir() || useFiles) && !haveName[name] {
|
||||
haveName[name] = true
|
||||
all = append(all, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find any directories containing Go files.
|
||||
// If some directory returned successfully, use that.
|
||||
if !haveGo {
|
||||
for _, d := range first {
|
||||
if !haveName[d.Name()] {
|
||||
haveName[d.Name()] = true
|
||||
all = append(all, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Built union. Add any missing directories needed to reach mount points.
|
||||
for old := range ns {
|
||||
if hasPathPrefix(old, path) && old != path {
|
||||
// Find next element after path in old.
|
||||
elem := old[len(path):]
|
||||
elem = strings.TrimPrefix(elem, "/")
|
||||
if i := strings.Index(elem, "/"); i >= 0 {
|
||||
elem = elem[:i]
|
||||
}
|
||||
if !haveName[elem] {
|
||||
haveName[elem] = true
|
||||
all = append(all, dirInfo(elem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(all) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Sort(byName(all))
|
||||
return all, nil
|
||||
}
|
||||
|
||||
// RootType returns the RootType for the given path in the namespace.
|
||||
func (ns NameSpace) RootType(path string) RootType {
|
||||
// We resolve the given path to a list of mountedFS and then return
|
||||
// the root type for the filesystem which contains the path.
|
||||
for _, m := range ns.resolve(path) {
|
||||
_, err := m.fs.ReadDir(m.translate(path))
|
||||
// Found a match, return the filesystem's root type
|
||||
if err == nil {
|
||||
return m.fs.RootType(path)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// byName implements sort.Interface.
|
||||
type byName []os.FileInfo
|
||||
|
||||
func (f byName) Len() int { return len(f) }
|
||||
func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
|
||||
func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
|
97
vendor/golang.org/x/tools/godoc/vfs/os.go
generated
vendored
Normal file
97
vendor/golang.org/x/tools/godoc/vfs/os.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
pathpkg "path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// 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.
|
||||
func OS(root string) FileSystem {
|
||||
var t RootType
|
||||
switch {
|
||||
case root == runtime.GOROOT():
|
||||
t = RootTypeGoRoot
|
||||
case isGoPath(root):
|
||||
t = RootTypeGoPath
|
||||
}
|
||||
return osFS{rootPath: root, rootType: t}
|
||||
}
|
||||
|
||||
type osFS struct {
|
||||
rootPath string
|
||||
rootType RootType
|
||||
}
|
||||
|
||||
func isGoPath(path string) bool {
|
||||
for _, bp := range filepath.SplitList(build.Default.GOPATH) {
|
||||
for _, gp := range filepath.SplitList(path) {
|
||||
if bp == gp {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (root osFS) String() string { return "os(" + root.rootPath + ")" }
|
||||
|
||||
// RootType returns the root type for the filesystem.
|
||||
//
|
||||
// Note that we ignore the path argument because roottype is a property of
|
||||
// this filesystem. But for other filesystems, the roottype might need to be
|
||||
// dynamically deduced at call time.
|
||||
func (root osFS) RootType(path string) RootType {
|
||||
return root.rootType
|
||||
}
|
||||
|
||||
func (root osFS) resolve(path string) string {
|
||||
// Clean the path so that it cannot possibly begin with ../.
|
||||
// If it did, the result of filepath.Join would be outside the
|
||||
// tree rooted at root. We probably won't ever see a path
|
||||
// with .. in it, but be safe anyway.
|
||||
path = pathpkg.Clean("/" + path)
|
||||
|
||||
return filepath.Join(root.rootPath, path)
|
||||
}
|
||||
|
||||
func (root osFS) Open(path string) (ReadSeekCloser, error) {
|
||||
f, err := os.Open(root.resolve(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
f.Close()
|
||||
return nil, fmt.Errorf("Open: %s is a directory", path)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (root osFS) Lstat(path string) (os.FileInfo, error) {
|
||||
return os.Lstat(root.resolve(path))
|
||||
}
|
||||
|
||||
func (root osFS) Stat(path string) (os.FileInfo, error) {
|
||||
return os.Stat(root.resolve(path))
|
||||
}
|
||||
|
||||
func (root osFS) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return ioutil.ReadDir(root.resolve(path)) // is sorted
|
||||
}
|
38
vendor/golang.org/x/tools/godoc/vfs/os_test.go
generated
vendored
Normal file
38
vendor/golang.org/x/tools/godoc/vfs/os_test.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vfs_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
func TestRootType(t *testing.T) {
|
||||
goPath := os.Getenv("GOPATH")
|
||||
var expectedType vfs.RootType
|
||||
if goPath == "" {
|
||||
expectedType = ""
|
||||
} else {
|
||||
expectedType = vfs.RootTypeGoPath
|
||||
}
|
||||
tests := []struct {
|
||||
path string
|
||||
fsType vfs.RootType
|
||||
}{
|
||||
{runtime.GOROOT(), vfs.RootTypeGoRoot},
|
||||
{goPath, expectedType},
|
||||
{"/tmp/", ""},
|
||||
}
|
||||
|
||||
for _, item := range tests {
|
||||
fs := vfs.OS(item.path)
|
||||
if fs.RootType("path") != item.fsType {
|
||||
t.Errorf("unexpected fsType. Expected- %v, Got- %v", item.fsType, fs.RootType("path"))
|
||||
}
|
||||
}
|
||||
}
|
58
vendor/golang.org/x/tools/godoc/vfs/vfs.go
generated
vendored
Normal file
58
vendor/golang.org/x/tools/godoc/vfs/vfs.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package vfs defines types for abstract file system access and provides an
|
||||
// implementation accessing the file system of the underlying OS.
|
||||
package vfs // import "golang.org/x/tools/godoc/vfs"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// RootType indicates the type of files contained within a directory.
|
||||
//
|
||||
// It is used to indicate whether a directory is the root
|
||||
// of a GOROOT, a GOPATH, or neither.
|
||||
// An empty string represents the case when a directory is neither.
|
||||
type RootType string
|
||||
|
||||
const (
|
||||
RootTypeGoRoot RootType = "GOROOT"
|
||||
RootTypeGoPath RootType = "GOPATH"
|
||||
)
|
||||
|
||||
// The FileSystem interface specifies the methods godoc is using
|
||||
// to access the file system for which it serves documentation.
|
||||
type FileSystem interface {
|
||||
Opener
|
||||
Lstat(path string) (os.FileInfo, error)
|
||||
Stat(path string) (os.FileInfo, error)
|
||||
ReadDir(path string) ([]os.FileInfo, error)
|
||||
RootType(path string) RootType
|
||||
String() string
|
||||
}
|
||||
|
||||
// Opener is a minimal virtual filesystem that can only open regular files.
|
||||
type Opener interface {
|
||||
Open(name string) (ReadSeekCloser, error)
|
||||
}
|
||||
|
||||
// A ReadSeekCloser can Read, Seek, and Close.
|
||||
type ReadSeekCloser interface {
|
||||
io.Reader
|
||||
io.Seeker
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// ReadFile reads the file named by path from fs and returns the contents.
|
||||
func ReadFile(fs Opener, path string) ([]byte, error) {
|
||||
rc, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rc.Close()
|
||||
return ioutil.ReadAll(rc)
|
||||
}
|
287
vendor/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go
generated
vendored
Normal file
287
vendor/golang.org/x/tools/godoc/vfs/zipfs/zipfs.go
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package zipfs file provides an implementation of the FileSystem
|
||||
// interface based on the contents of a .zip file.
|
||||
//
|
||||
// Assumptions:
|
||||
//
|
||||
// - The file paths stored in the zip file must use a slash ('/') as path
|
||||
// separator; and they must be relative (i.e., they must not start with
|
||||
// a '/' - this is usually the case if the file was created w/o special
|
||||
// options).
|
||||
// - The zip file system treats the file paths found in the zip internally
|
||||
// like absolute paths w/o a leading '/'; i.e., the paths are considered
|
||||
// relative to the root of the file system.
|
||||
// - All path arguments to file system methods must be absolute paths.
|
||||
package zipfs // import "golang.org/x/tools/godoc/vfs/zipfs"
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
// zipFI is the zip-file based implementation of FileInfo
|
||||
type zipFI struct {
|
||||
name string // directory-local name
|
||||
file *zip.File // nil for a directory
|
||||
}
|
||||
|
||||
func (fi zipFI) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
|
||||
func (fi zipFI) Size() int64 {
|
||||
if f := fi.file; f != nil {
|
||||
return int64(f.UncompressedSize)
|
||||
}
|
||||
return 0 // directory
|
||||
}
|
||||
|
||||
func (fi zipFI) ModTime() time.Time {
|
||||
if f := fi.file; f != nil {
|
||||
return f.ModTime()
|
||||
}
|
||||
return time.Time{} // directory has no modified time entry
|
||||
}
|
||||
|
||||
func (fi zipFI) Mode() os.FileMode {
|
||||
if fi.file == nil {
|
||||
// Unix directories typically are executable, hence 555.
|
||||
return os.ModeDir | 0555
|
||||
}
|
||||
return 0444
|
||||
}
|
||||
|
||||
func (fi zipFI) IsDir() bool {
|
||||
return fi.file == nil
|
||||
}
|
||||
|
||||
func (fi zipFI) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// zipFS is the zip-file based implementation of FileSystem
|
||||
type zipFS struct {
|
||||
*zip.ReadCloser
|
||||
list zipList
|
||||
name string
|
||||
}
|
||||
|
||||
func (fs *zipFS) String() string {
|
||||
return "zip(" + fs.name + ")"
|
||||
}
|
||||
|
||||
func (fs *zipFS) RootType(abspath string) vfs.RootType {
|
||||
var t vfs.RootType
|
||||
switch {
|
||||
case abspath == runtime.GOROOT():
|
||||
t = vfs.RootTypeGoRoot
|
||||
case isGoPath(abspath):
|
||||
t = vfs.RootTypeGoPath
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func isGoPath(path string) bool {
|
||||
for _, p := range filepath.SplitList(build.Default.GOPATH) {
|
||||
if p == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (fs *zipFS) Close() error {
|
||||
fs.list = nil
|
||||
return fs.ReadCloser.Close()
|
||||
}
|
||||
|
||||
func zipPath(name string) (string, error) {
|
||||
name = path.Clean(name)
|
||||
if !path.IsAbs(name) {
|
||||
return "", fmt.Errorf("stat: not an absolute path: %s", name)
|
||||
}
|
||||
return name[1:], nil // strip leading '/'
|
||||
}
|
||||
|
||||
func isRoot(abspath string) bool {
|
||||
return path.Clean(abspath) == "/"
|
||||
}
|
||||
|
||||
func (fs *zipFS) stat(abspath string) (int, zipFI, error) {
|
||||
if isRoot(abspath) {
|
||||
return 0, zipFI{
|
||||
name: "",
|
||||
file: nil,
|
||||
}, nil
|
||||
}
|
||||
zippath, err := zipPath(abspath)
|
||||
if err != nil {
|
||||
return 0, zipFI{}, err
|
||||
}
|
||||
i, exact := fs.list.lookup(zippath)
|
||||
if i < 0 {
|
||||
// zippath has leading '/' stripped - print it explicitly
|
||||
return -1, zipFI{}, &os.PathError{Path: "/" + zippath, Err: os.ErrNotExist}
|
||||
}
|
||||
_, name := path.Split(zippath)
|
||||
var file *zip.File
|
||||
if exact {
|
||||
file = fs.list[i] // exact match found - must be a file
|
||||
}
|
||||
return i, zipFI{name, file}, nil
|
||||
}
|
||||
|
||||
func (fs *zipFS) Open(abspath string) (vfs.ReadSeekCloser, error) {
|
||||
_, fi, err := fs.stat(abspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return nil, fmt.Errorf("Open: %s is a directory", abspath)
|
||||
}
|
||||
r, err := fi.file.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &zipSeek{fi.file, r}, nil
|
||||
}
|
||||
|
||||
type zipSeek struct {
|
||||
file *zip.File
|
||||
io.ReadCloser
|
||||
}
|
||||
|
||||
func (f *zipSeek) Seek(offset int64, whence int) (int64, error) {
|
||||
if whence == 0 && offset == 0 {
|
||||
r, err := f.file.Open()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
f.Close()
|
||||
f.ReadCloser = r
|
||||
return 0, nil
|
||||
}
|
||||
return 0, fmt.Errorf("unsupported Seek in %s", f.file.Name)
|
||||
}
|
||||
|
||||
func (fs *zipFS) Lstat(abspath string) (os.FileInfo, error) {
|
||||
_, fi, err := fs.stat(abspath)
|
||||
return fi, err
|
||||
}
|
||||
|
||||
func (fs *zipFS) Stat(abspath string) (os.FileInfo, error) {
|
||||
_, fi, err := fs.stat(abspath)
|
||||
return fi, err
|
||||
}
|
||||
|
||||
func (fs *zipFS) ReadDir(abspath string) ([]os.FileInfo, error) {
|
||||
i, fi, err := fs.stat(abspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return nil, fmt.Errorf("ReadDir: %s is not a directory", abspath)
|
||||
}
|
||||
|
||||
var list []os.FileInfo
|
||||
|
||||
// make dirname the prefix that file names must start with to be considered
|
||||
// in this directory. we must special case the root directory because, per
|
||||
// the spec of this package, zip file entries MUST NOT start with /, so we
|
||||
// should not append /, as we would in every other case.
|
||||
var dirname string
|
||||
if isRoot(abspath) {
|
||||
dirname = ""
|
||||
} else {
|
||||
zippath, err := zipPath(abspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dirname = zippath + "/"
|
||||
}
|
||||
prevname := ""
|
||||
for _, e := range fs.list[i:] {
|
||||
if !strings.HasPrefix(e.Name, dirname) {
|
||||
break // not in the same directory anymore
|
||||
}
|
||||
name := e.Name[len(dirname):] // local name
|
||||
file := e
|
||||
if i := strings.IndexRune(name, '/'); i >= 0 {
|
||||
// We infer directories from files in subdirectories.
|
||||
// If we have x/y, return a directory entry for x.
|
||||
name = name[0:i] // keep local directory name only
|
||||
file = nil
|
||||
}
|
||||
// If we have x/y and x/z, don't return two directory entries for x.
|
||||
// TODO(gri): It should be possible to do this more efficiently
|
||||
// by determining the (fs.list) range of local directory entries
|
||||
// (via two binary searches).
|
||||
if name != prevname {
|
||||
list = append(list, zipFI{name, file})
|
||||
prevname = name
|
||||
}
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func New(rc *zip.ReadCloser, name string) vfs.FileSystem {
|
||||
list := make(zipList, len(rc.File))
|
||||
copy(list, rc.File) // sort a copy of rc.File
|
||||
sort.Sort(list)
|
||||
return &zipFS{rc, list, name}
|
||||
}
|
||||
|
||||
type zipList []*zip.File
|
||||
|
||||
// zipList implements sort.Interface
|
||||
func (z zipList) Len() int { return len(z) }
|
||||
func (z zipList) Less(i, j int) bool { return z[i].Name < z[j].Name }
|
||||
func (z zipList) Swap(i, j int) { z[i], z[j] = z[j], z[i] }
|
||||
|
||||
// lookup returns the smallest index of an entry with an exact match
|
||||
// for name, or an inexact match starting with name/. If there is no
|
||||
// such entry, the result is -1, false.
|
||||
func (z zipList) lookup(name string) (index int, exact bool) {
|
||||
// look for exact match first (name comes before name/ in z)
|
||||
i := sort.Search(len(z), func(i int) bool {
|
||||
return name <= z[i].Name
|
||||
})
|
||||
if i >= len(z) {
|
||||
return -1, false
|
||||
}
|
||||
// 0 <= i < len(z)
|
||||
if z[i].Name == name {
|
||||
return i, true
|
||||
}
|
||||
|
||||
// look for inexact match (must be in z[i:], if present)
|
||||
z = z[i:]
|
||||
name += "/"
|
||||
j := sort.Search(len(z), func(i int) bool {
|
||||
return name <= z[i].Name
|
||||
})
|
||||
if j >= len(z) {
|
||||
return -1, false
|
||||
}
|
||||
// 0 <= j < len(z)
|
||||
if strings.HasPrefix(z[j].Name, name) {
|
||||
return i + j, false
|
||||
}
|
||||
|
||||
return -1, false
|
||||
}
|
189
vendor/golang.org/x/tools/godoc/vfs/zipfs/zipfs_test.go
generated
vendored
Normal file
189
vendor/golang.org/x/tools/godoc/vfs/zipfs/zipfs_test.go
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.package zipfs
|
||||
package zipfs
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
// files to use to build zip used by zipfs in testing; maps path : contents
|
||||
files = map[string]string{"foo": "foo", "bar/baz": "baz", "a/b/c": "c"}
|
||||
|
||||
// expected info for each entry in a file system described by files
|
||||
tests = []struct {
|
||||
Path string
|
||||
IsDir bool
|
||||
IsRegular bool
|
||||
Name string
|
||||
Contents string
|
||||
Files map[string]bool
|
||||
}{
|
||||
{"/", true, false, "", "", map[string]bool{"foo": true, "bar": true, "a": true}},
|
||||
{"//", true, false, "", "", map[string]bool{"foo": true, "bar": true, "a": true}},
|
||||
{"/foo", false, true, "foo", "foo", nil},
|
||||
{"/foo/", false, true, "foo", "foo", nil},
|
||||
{"/foo//", false, true, "foo", "foo", nil},
|
||||
{"/bar", true, false, "bar", "", map[string]bool{"baz": true}},
|
||||
{"/bar/", true, false, "bar", "", map[string]bool{"baz": true}},
|
||||
{"/bar/baz", false, true, "baz", "baz", nil},
|
||||
{"//bar//baz", false, true, "baz", "baz", nil},
|
||||
{"/a/b", true, false, "b", "", map[string]bool{"c": true}},
|
||||
}
|
||||
|
||||
// to be initialized in setup()
|
||||
fs vfs.FileSystem
|
||||
statFuncs []statFunc
|
||||
)
|
||||
|
||||
type statFunc struct {
|
||||
Name string
|
||||
Func func(string) (os.FileInfo, error)
|
||||
}
|
||||
|
||||
func TestMain(t *testing.M) {
|
||||
if err := setup(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error setting up zipfs testing state: %v.\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(t.Run())
|
||||
}
|
||||
|
||||
// setups state each of the tests uses
|
||||
func setup() error {
|
||||
// create zipfs
|
||||
b := new(bytes.Buffer)
|
||||
zw := zip.NewWriter(b)
|
||||
for file, contents := range files {
|
||||
w, err := zw.Create(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.WriteString(w, contents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
zw.Close()
|
||||
zr, err := zip.NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rc := &zip.ReadCloser{
|
||||
Reader: *zr,
|
||||
}
|
||||
fs = New(rc, "foo")
|
||||
|
||||
// pull out different stat functions
|
||||
statFuncs = []statFunc{
|
||||
{"Stat", fs.Stat},
|
||||
{"Lstat", fs.Lstat},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestZipFSReadDir(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if test.IsDir {
|
||||
infos, err := fs.ReadDir(test.Path)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to read directory %v\n", test.Path)
|
||||
continue
|
||||
}
|
||||
got := make(map[string]bool)
|
||||
for _, info := range infos {
|
||||
got[info.Name()] = true
|
||||
}
|
||||
if want := test.Files; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("ReadDir %v got %v\nwanted %v\n", test.Path, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestZipFSStatFuncs(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
for _, statFunc := range statFuncs {
|
||||
|
||||
// test can stat
|
||||
info, err := statFunc.Func(test.Path)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error using %v for %v: %v\n", statFunc.Name, test.Path, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// test info.Name()
|
||||
if got, want := info.Name(), test.Name; got != want {
|
||||
t.Errorf("Using %v for %v info.Name() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
|
||||
}
|
||||
// test info.IsDir()
|
||||
if got, want := info.IsDir(), test.IsDir; got != want {
|
||||
t.Errorf("Using %v for %v info.IsDir() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
|
||||
}
|
||||
// test info.Mode().IsDir()
|
||||
if got, want := info.Mode().IsDir(), test.IsDir; got != want {
|
||||
t.Errorf("Using %v for %v info.Mode().IsDir() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
|
||||
}
|
||||
// test info.Mode().IsRegular()
|
||||
if got, want := info.Mode().IsRegular(), test.IsRegular; got != want {
|
||||
t.Errorf("Using %v for %v info.Mode().IsRegular() got %v wanted %v\n", statFunc.Name, test.Path, got, want)
|
||||
}
|
||||
// test info.Size()
|
||||
if test.IsRegular {
|
||||
if got, want := info.Size(), int64(len(test.Contents)); got != want {
|
||||
t.Errorf("Using %v for %v inf.Size() got %v wanted %v", statFunc.Name, test.Path, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestZipFSNotExist(t *testing.T) {
|
||||
_, err := fs.Open("/does-not-exist")
|
||||
if err == nil {
|
||||
t.Fatalf("Expected an error.\n")
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
t.Errorf("Expected an error satisfying os.IsNotExist: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestZipFSOpenSeek(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if test.IsRegular {
|
||||
|
||||
// test Open()
|
||||
f, err := fs.Open(test.Path)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// test Seek() multiple times
|
||||
for i := 0; i < 3; i++ {
|
||||
all, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if got, want := string(all), test.Contents; got != want {
|
||||
t.Errorf("File contents for %v got %v wanted %v\n", test.Path, got, want)
|
||||
}
|
||||
f.Seek(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user