Do vendoring

This commit is contained in:
Andrey Nering
2017-02-27 17:04:44 -03:00
parent b8b52b94f9
commit 93dabdd9a8
24 changed files with 10001 additions and 0 deletions

25
vendor/github.com/mattn/go-zglob/README.md generated vendored Normal file
View File

@@ -0,0 +1,25 @@
# go-zglob
[![Build Status](https://travis-ci.org/mattn/go-zglob.svg)](https://travis-ci.org/mattn/go-zglob)
zglob
## Usage
```go
matches, err := zglob.Glob(`./foo/b*/**/z*.txt`)
```
## Installation
```
$ go get github.com/mattn/go-zglob
```
## License
MIT
## Author
Yasuhiro Matsumoto (a.k.a mattn)

172
vendor/github.com/mattn/go-zglob/fastwalk/fastwalk.go generated vendored Normal file
View File

@@ -0,0 +1,172 @@
// 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.
// A faster implementation of filepath.Walk.
//
// filepath.Walk's design necessarily calls os.Lstat on each file,
// even if the caller needs less info. And goimports only need to know
// the type of each file. The kernel interface provides the type in
// the Readdir call but the standard library ignored it.
// fastwalk_unix.go contains a fork of the syscall routines.
//
// See golang.org/issue/16399
package fastwalk
import (
"errors"
"os"
"path/filepath"
"runtime"
)
// traverseLink is a sentinel error for fastWalk, similar to filepath.SkipDir.
var traverseLink = errors.New("traverse symlink, assuming target is a directory")
// FastWalk walks the file tree rooted at root, calling walkFn for
// each file or directory in the tree, including root.
//
// If fastWalk returns filepath.SkipDir, the directory is skipped.
//
// Unlike filepath.Walk:
// * file stat calls must be done by the user.
// The only provided metadata is the file type, which does not include
// any permission bits.
// * multiple goroutines stat the filesystem concurrently. The provided
// walkFn must be safe for concurrent use.
// * fastWalk can follow symlinks if walkFn returns the traverseLink
// sentinel error. It is the walkFn's responsibility to prevent
// fastWalk from going into symlink cycles.
func FastWalk(root string, walkFn func(path string, typ os.FileMode) error) error {
// TODO(bradfitz): make numWorkers configurable? We used a
// minimum of 4 to give the kernel more info about multiple
// things we want, in hopes its I/O scheduling can take
// advantage of that. Hopefully most are in cache. Maybe 4 is
// even too low of a minimum. Profile more.
numWorkers := 4
if n := runtime.NumCPU(); n > numWorkers {
numWorkers = n
}
w := &walker{
fn: walkFn,
enqueuec: make(chan walkItem, numWorkers), // buffered for performance
workc: make(chan walkItem, numWorkers), // buffered for performance
donec: make(chan struct{}),
// buffered for correctness & not leaking goroutines:
resc: make(chan error, numWorkers),
}
defer close(w.donec)
// TODO(bradfitz): start the workers as needed? maybe not worth it.
for i := 0; i < numWorkers; i++ {
go w.doWork()
}
todo := []walkItem{{dir: root}}
out := 0
for {
workc := w.workc
var workItem walkItem
if len(todo) == 0 {
workc = nil
} else {
workItem = todo[len(todo)-1]
}
select {
case workc <- workItem:
todo = todo[:len(todo)-1]
out++
case it := <-w.enqueuec:
todo = append(todo, it)
case err := <-w.resc:
out--
if err != nil {
return err
}
if out == 0 && len(todo) == 0 {
// It's safe to quit here, as long as the buffered
// enqueue channel isn't also readable, which might
// happen if the worker sends both another unit of
// work and its result before the other select was
// scheduled and both w.resc and w.enqueuec were
// readable.
select {
case it := <-w.enqueuec:
todo = append(todo, it)
default:
return nil
}
}
}
}
}
// doWork reads directories as instructed (via workc) and runs the
// user's callback function.
func (w *walker) doWork() {
for {
select {
case <-w.donec:
return
case it := <-w.workc:
w.resc <- w.walk(it.dir, !it.callbackDone)
}
}
}
type walker struct {
fn func(path string, typ os.FileMode) error
donec chan struct{} // closed on fastWalk's return
workc chan walkItem // to workers
enqueuec chan walkItem // from workers
resc chan error // from workers
}
type walkItem struct {
dir string
callbackDone bool // callback already called; don't do it again
}
func (w *walker) enqueue(it walkItem) {
select {
case w.enqueuec <- it:
case <-w.donec:
}
}
func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error {
joined := dirName + string(os.PathSeparator) + baseName
if typ == os.ModeDir {
w.enqueue(walkItem{dir: joined})
return nil
}
err := w.fn(joined, typ)
if typ == os.ModeSymlink {
if err == traverseLink {
// Set callbackDone so we don't call it twice for both the
// symlink-as-symlink and the symlink-as-directory later:
w.enqueue(walkItem{dir: joined, callbackDone: true})
return nil
}
if err == filepath.SkipDir {
// Permit SkipDir on symlinks too.
return nil
}
}
return err
}
func (w *walker) walk(root string, runUserCallback bool) error {
if runUserCallback {
err := w.fn(root, os.ModeDir)
if err == filepath.SkipDir {
return nil
}
if err != nil {
return err
}
}
return readDir(root, w.onDirEnt)
}

View File

@@ -0,0 +1,13 @@
// 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.
// +build freebsd openbsd netbsd
package fastwalk
import "syscall"
func direntInode(dirent *syscall.Dirent) uint64 {
return uint64(dirent.Fileno)
}

View File

@@ -0,0 +1,13 @@
// 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.
// +build linux,!appengine darwin
package fastwalk
import "syscall"
func direntInode(dirent *syscall.Dirent) uint64 {
return uint64(dirent.Ino)
}

View File

@@ -0,0 +1,29 @@
// 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.
// +build appengine !linux,!darwin,!freebsd,!openbsd,!netbsd
package fastwalk
import (
"io/ioutil"
"os"
)
// readDir calls fn for each directory entry in dirName.
// It does not descend into directories or follow symlinks.
// If fn returns a non-nil error, readDir returns with that error
// immediately.
func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
fis, err := ioutil.ReadDir(dirName)
if err != nil {
return err
}
for _, fi := range fis {
if err := fn(dirName, fi.Name(), fi.Mode()&os.ModeType); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,122 @@
// 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.
// +build linux,!appengine darwin freebsd openbsd netbsd
package fastwalk
import (
"bytes"
"fmt"
"os"
"syscall"
"unsafe"
)
const blockSize = 8 << 10
// unknownFileMode is a sentinel (and bogus) os.FileMode
// value used to represent a syscall.DT_UNKNOWN Dirent.Type.
const unknownFileMode os.FileMode = os.ModeNamedPipe | os.ModeSocket | os.ModeDevice
func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
fd, err := syscall.Open(dirName, 0, 0)
if err != nil {
return err
}
defer syscall.Close(fd)
// The buffer must be at least a block long.
buf := make([]byte, blockSize) // stack-allocated; doesn't escape
bufp := 0 // starting read position in buf
nbuf := 0 // end valid data in buf
for {
if bufp >= nbuf {
bufp = 0
nbuf, err = syscall.ReadDirent(fd, buf)
if err != nil {
return os.NewSyscallError("readdirent", err)
}
if nbuf <= 0 {
return nil
}
}
consumed, name, typ := parseDirEnt(buf[bufp:nbuf])
bufp += consumed
if name == "" || name == "." || name == ".." {
continue
}
// Fallback for filesystems (like old XFS) that don't
// support Dirent.Type and have DT_UNKNOWN (0) there
// instead.
if typ == unknownFileMode {
fi, err := os.Lstat(dirName + "/" + name)
if err != nil {
// It got deleted in the meantime.
if os.IsNotExist(err) {
continue
}
return err
}
typ = fi.Mode() & os.ModeType
}
if err := fn(dirName, name, typ); err != nil {
return err
}
}
}
func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) {
// golang.org/issue/15653
dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0]))
if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v {
panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v))
}
if len(buf) < int(dirent.Reclen) {
panic(fmt.Sprintf("buf size %d < record length %d", len(buf), dirent.Reclen))
}
consumed = int(dirent.Reclen)
if direntInode(dirent) == 0 { // File absent in directory.
return
}
switch dirent.Type {
case syscall.DT_REG:
typ = 0
case syscall.DT_DIR:
typ = os.ModeDir
case syscall.DT_LNK:
typ = os.ModeSymlink
case syscall.DT_BLK:
typ = os.ModeDevice
case syscall.DT_FIFO:
typ = os.ModeNamedPipe
case syscall.DT_SOCK:
typ = os.ModeSocket
case syscall.DT_UNKNOWN:
typ = unknownFileMode
default:
// Skip weird things.
// It's probably a DT_WHT (http://lwn.net/Articles/325369/)
// or something. Revisit if/when this package is moved outside
// of goimports. goimports only cares about regular files,
// symlinks, and directories.
return
}
nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
nameLen := bytes.IndexByte(nameBuf[:], 0)
if nameLen < 0 {
panic("failed to find terminating 0 byte in dirent")
}
// Special cases for common things:
if nameLen == 1 && nameBuf[0] == '.' {
name = "."
} else if nameLen == 2 && nameBuf[0] == '.' && nameBuf[1] == '.' {
name = ".."
} else {
name = string(nameBuf[:nameLen])
}
return
}

175
vendor/github.com/mattn/go-zglob/zglob.go generated vendored Normal file
View File

@@ -0,0 +1,175 @@
package zglob
import (
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"github.com/mattn/go-zglob/fastwalk"
)
var (
envre = regexp.MustCompile(`^(\$[a-zA-Z][a-zA-Z0-9_]+|\$\([a-zA-Z][a-zA-Z0-9_]+\))$`)
mu sync.Mutex
)
type zenv struct {
dre *regexp.Regexp
fre *regexp.Regexp
root string
}
func makePattern(pattern string) (*zenv, error) {
globmask := ""
root := ""
for n, i := range strings.Split(filepath.ToSlash(pattern), "/") {
if root == "" && strings.Index(i, "*") != -1 {
if globmask == "" {
root = "."
} else {
root = filepath.ToSlash(globmask)
}
}
if n == 0 && i == "~" {
if runtime.GOOS == "windows" {
i = os.Getenv("USERPROFILE")
} else {
i = os.Getenv("HOME")
}
}
if envre.MatchString(i) {
i = strings.Trim(strings.Trim(os.Getenv(i[1:]), "()"), `"`)
}
globmask = filepath.Join(globmask, i)
if n == 0 {
if runtime.GOOS == "windows" && filepath.VolumeName(i) != "" {
globmask = i + "/"
} else if len(globmask) == 0 {
globmask = "/"
}
}
}
if root == "" {
return &zenv{
dre: nil,
fre: nil,
root: "",
}, nil
}
if globmask == "" {
globmask = "."
}
globmask = filepath.ToSlash(filepath.Clean(globmask))
cc := []rune(globmask)
dirmask := ""
filemask := ""
for i := 0; i < len(cc); i++ {
if cc[i] == '*' {
if i < len(cc)-2 && cc[i+1] == '*' && cc[i+2] == '/' {
filemask += "(.*/)?"
dirmask = filemask
i += 2
} else {
filemask += "[^/]*"
}
} else {
c := cc[i]
if c == '/' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || 255 < c {
filemask += string(c)
} else {
filemask += fmt.Sprintf("[\\x%02X]", c)
}
if c == '/' && dirmask == "" && strings.Index(filemask, "*") != -1 {
dirmask = filemask
}
}
}
if dirmask == "" {
dirmask = filemask
}
if len(filemask) > 0 && filemask[len(filemask)-1] == '/' {
if root == "" {
root = filemask
}
filemask += "[^/]*"
}
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
dirmask = "(?i:" + dirmask + ")"
filemask = "(?i:" + filemask + ")"
}
return &zenv{
dre: regexp.MustCompile("^" + dirmask),
fre: regexp.MustCompile("^" + filemask + "$"),
root: filepath.Clean(root),
}, nil
}
func Glob(pattern string) ([]string, error) {
zenv, err := makePattern(pattern)
if err != nil {
return nil, err
}
if zenv.root == "" {
_, err := os.Stat(pattern)
if err != nil {
return nil, os.ErrNotExist
}
return []string{pattern}, nil
}
relative := !filepath.IsAbs(pattern)
matches := []string{}
fastwalk.FastWalk(zenv.root, func(path string, info os.FileMode) error {
if zenv.root == "." && len(zenv.root) < len(path) {
path = path[len(zenv.root)+1:]
}
path = filepath.ToSlash(path)
if info.IsDir() {
if path == "." || len(path) <= len(zenv.root) {
return nil
}
if !zenv.dre.MatchString(path + "/") {
return filepath.SkipDir
}
}
if zenv.fre.MatchString(path) {
if relative && filepath.IsAbs(path) {
path = path[len(zenv.root)+1:]
}
mu.Lock()
matches = append(matches, path)
mu.Unlock()
}
return nil
})
return matches, nil
}
func Match(pattern, name string) (matched bool, err error) {
zenv, err := makePattern(pattern)
if err != nil {
return false, err
}
if zenv.root == "" {
return pattern == name, nil
}
name = filepath.ToSlash(name)
if name == "." || len(name) <= len(zenv.root) {
return false, nil
}
if zenv.fre.MatchString(name) {
return true, nil
}
return false, nil
}