expressions working

Signed-off-by: Casey Lee <cplee@nektos.com>
This commit is contained in:
Casey Lee
2020-02-12 23:27:37 -08:00
parent 409060c847
commit e40ab0145f
114 changed files with 32361 additions and 0 deletions

20
vendor/gopkg.in/godo.v2/glob/fileAsset.go generated vendored Normal file
View File

@@ -0,0 +1,20 @@
package glob
import "os"
// FileAsset contains file information and path from globbing.
type FileAsset struct {
os.FileInfo
// Path to asset
Path string
}
// Stat updates the stat of this asset.
func (fa *FileAsset) Stat() (*os.FileInfo, error) {
fi, err := os.Stat(fa.Path)
if err != nil {
return nil, err
}
fa.FileInfo = fi
return &fa.FileInfo, nil
}

277
vendor/gopkg.in/godo.v2/glob/glob.go generated vendored Normal file
View File

@@ -0,0 +1,277 @@
package glob
import (
"bytes"
"fmt"
//"log"
"os"
gpath "path"
"path/filepath"
"regexp"
"strings"
"sync"
"unicode/utf8"
"github.com/MichaelTJones/walk"
)
const (
// NotSlash is any rune but path separator.
notSlash = "[^/]"
// AnyRune is zero or more non-path separators.
anyRune = notSlash + "*"
// ZeroOrMoreDirectories is used by ** patterns.
zeroOrMoreDirectories = `(?:[.{}\w\-\ ]+\/)*`
// TrailingStarStar matches everything inside directory.
trailingStarStar = "/**"
// SlashStarStarSlash maches zero or more directories.
slashStarStarSlash = "/**/"
)
// RegexpInfo contains additional info about the Regexp created by a glob pattern.
type RegexpInfo struct {
Regexp *regexp.Regexp
Negate bool
Path string
Glob string
}
// MatchString matches a string with either a regexp or direct string match
func (ri *RegexpInfo) MatchString(s string) bool {
if ri.Regexp != nil {
return ri.Regexp.MatchString(s)
} else if ri.Path != "" {
return strings.HasSuffix(s, ri.Path)
}
return false
}
// Globexp builds a regular express from from extended glob pattern and then
// returns a Regexp object.
func Globexp(glob string) *regexp.Regexp {
var re bytes.Buffer
re.WriteString("^")
i, inGroup, L := 0, false, len(glob)
for i < L {
r, w := utf8.DecodeRuneInString(glob[i:])
switch r {
default:
re.WriteRune(r)
case '\\', '$', '^', '+', '.', '(', ')', '=', '!', '|':
re.WriteRune('\\')
re.WriteRune(r)
case '/':
// TODO optimize later, string could be long
rest := glob[i:]
re.WriteRune('/')
if strings.HasPrefix(rest, "/**/") {
re.WriteString(zeroOrMoreDirectories)
w *= 4
} else if rest == "/**" {
re.WriteString(".*")
w *= 3
}
case '?':
re.WriteRune('.')
case '[', ']':
re.WriteRune(r)
case '{':
if i < L-1 {
if glob[i+1:i+2] == "{" {
re.WriteString("\\{")
w *= 2
break
}
}
inGroup = true
re.WriteRune('(')
case '}':
if inGroup {
inGroup = false
re.WriteRune(')')
} else {
re.WriteRune('}')
}
case ',':
if inGroup {
re.WriteRune('|')
} else {
re.WriteRune('\\')
re.WriteRune(r)
}
case '*':
rest := glob[i:]
if strings.HasPrefix(rest, "**/") {
re.WriteString(zeroOrMoreDirectories)
w *= 3
} else {
re.WriteString(anyRune)
}
}
i += w
}
re.WriteString("$")
//log.Printf("regex string %s", re.String())
return regexp.MustCompile(re.String())
}
// Glob returns files and dirctories that match patterns. Patterns must use
// slashes, even Windows.
//
// Special chars.
//
// /**/ - match zero or more directories
// {a,b} - match a or b, no spaces
// * - match any non-separator char
// ? - match a single non-separator char
// **/ - match any directory, start of pattern only
// /** - match any this directory, end of pattern only
// ! - removes files from resultset, start of pattern only
//
func Glob(patterns []string) ([]*FileAsset, []*RegexpInfo, error) {
// TODO very inefficient and unintelligent, optimize later
m := map[string]*FileAsset{}
regexps := []*RegexpInfo{}
for _, pattern := range patterns {
remove := strings.HasPrefix(pattern, "!")
if remove {
pattern = pattern[1:]
if hasMeta(pattern) {
re := Globexp(pattern)
regexps = append(regexps, &RegexpInfo{Regexp: re, Glob: pattern, Negate: true})
for path := range m {
if re.MatchString(path) {
m[path] = nil
}
}
} else {
path := gpath.Clean(pattern)
m[path] = nil
regexps = append(regexps, &RegexpInfo{Path: path, Glob: pattern, Negate: true})
}
} else {
if hasMeta(pattern) {
re := Globexp(pattern)
regexps = append(regexps, &RegexpInfo{Regexp: re, Glob: pattern})
root := PatternRoot(pattern)
if root == "" {
return nil, nil, fmt.Errorf("Cannot get root from pattern: %s", pattern)
}
fileAssets, err := walkFiles(root)
if err != nil {
return nil, nil, err
}
for _, file := range fileAssets {
if re.MatchString(file.Path) {
// TODO closure problem assigning &file
tmp := file
m[file.Path] = tmp
}
}
} else {
path := gpath.Clean(pattern)
info, err := os.Stat(path)
if err != nil {
return nil, nil, err
}
regexps = append(regexps, &RegexpInfo{Path: path, Glob: pattern, Negate: false})
fa := &FileAsset{Path: path, FileInfo: info}
m[path] = fa
}
}
}
//log.Printf("m %v", m)
keys := []*FileAsset{}
for _, it := range m {
if it != nil {
keys = append(keys, it)
}
}
return keys, regexps, nil
}
// hasMeta determines if a path has special chars used to build a Regexp.
func hasMeta(path string) bool {
return strings.IndexAny(path, "*?[{") >= 0
}
func isDir(path string) bool {
st, err := os.Stat(path)
if os.IsNotExist(err) {
return false
}
return st.IsDir()
}
// PatternRoot gets a real directory root from a pattern. The directory
// returned is used as the start location for globbing.
func PatternRoot(s string) string {
if isDir(s) {
return s
}
// No directory in pattern
parts := strings.Split(s, "/")
if len(parts) == 1 {
return "."
}
// parts returns an empty string at positio 0 if the s starts with "/"
root := ""
// Build path until a dirname has a char used to build regex
for i, part := range parts {
if hasMeta(part) {
break
}
if i > 0 {
root += "/"
}
root += part
}
// Default to cwd
if root == "" {
root = "."
}
return root
}
// walkFiles walks a directory starting at root returning all directories and files
// include those found in subdirectories.
func walkFiles(root string) ([]*FileAsset, error) {
fileAssets := []*FileAsset{}
var lock sync.Mutex
visitor := func(path string, info os.FileInfo, err error) error {
// if err != nil {
// fmt.Println("visitor err", err.Error(), "root", root)
// }
if err == nil {
lock.Lock()
fileAssets = append(fileAssets, &FileAsset{FileInfo: info, Path: filepath.ToSlash(path)})
lock.Unlock()
}
return nil
}
err := walk.Walk(root, visitor)
if err != nil {
return nil, err
}
return fileAssets, nil
}

164
vendor/gopkg.in/godo.v2/glob/watchCriteria.go generated vendored Normal file
View File

@@ -0,0 +1,164 @@
package glob
import (
"fmt"
"path/filepath"
"regexp"
"strings"
"github.com/mgutz/str"
)
// WatchCriterion is the criteria needed to test if a file
// matches a pattern.
type WatchCriterion struct {
// Root is the root directory to start watching.
Root string
// Includes are the regexp for including files
IncludesRegexp []*regexp.Regexp
// Excludes are the regexp for excluding files
ExcludesRegexp []*regexp.Regexp
Includes []string
Excludes []string
}
func newWatchCriterion(r string) *WatchCriterion {
return &WatchCriterion{
Root: r,
IncludesRegexp: []*regexp.Regexp{},
ExcludesRegexp: []*regexp.Regexp{},
Includes: []string{},
Excludes: []string{},
}
}
// WatchCriteria is the set of criterion to watch one or more glob patterns.
type WatchCriteria struct {
Items []*WatchCriterion
}
func newWatchCriteria() *WatchCriteria {
return &WatchCriteria{
Items: []*WatchCriterion{},
}
}
func (cr *WatchCriteria) findParent(root string) *WatchCriterion {
for _, item := range cr.Items {
if item.Root == root || strings.Contains(item.Root, root) {
return item
}
}
return nil
}
func (cr *WatchCriteria) add(glob string) error {
var err error
if glob == "" || glob == "!" {
return nil
}
isExclude := strings.HasPrefix(glob, "!")
if isExclude {
glob = glob[1:]
}
// determine if the root of pattern already exists
root := PatternRoot(glob)
root, err = filepath.Abs(root)
if err != nil {
return err
}
root = filepath.ToSlash(root)
cri := cr.findParent(root)
if cri == nil {
cri = newWatchCriterion(root)
cr.Items = append(cr.Items, cri)
}
glob, err = filepath.Abs(glob)
if err != nil {
return err
}
// add glob to {in,ex}cludes
if isExclude {
if str.SliceIndexOf(cri.Excludes, glob) < 0 {
re := Globexp(glob)
cri.ExcludesRegexp = append(cri.ExcludesRegexp, re)
cri.Excludes = append(cri.Excludes, glob)
}
} else {
if str.SliceIndexOf(cri.Includes, glob) < 0 {
re := Globexp(glob)
cri.IncludesRegexp = append(cri.IncludesRegexp, re)
cri.Includes = append(cri.Includes, glob)
}
}
return nil
}
// Roots returns the root paths of all criteria.
func (cr *WatchCriteria) Roots() []string {
if cr.Items == nil || len(cr.Items) == 0 {
return nil
}
roots := make([]string, len(cr.Items))
for i, it := range cr.Items {
roots[i] = it.Root
}
return roots
}
// Matches determines if pth is matched by internal criteria.
func (cr *WatchCriteria) Matches(pth string) bool {
match := false
pth = filepath.ToSlash(pth)
for _, it := range cr.Items {
// if sub path
if strings.HasPrefix(pth, it.Root) {
// check if matches an include pattern
for _, re := range it.IncludesRegexp {
if re.MatchString(pth) {
match = true
break
}
}
// when found, check if it is excluded
if match {
for _, re := range it.ExcludesRegexp {
if re.MatchString(pth) {
match = false
break
}
}
if match {
return true
}
}
}
}
return false
}
// EffectiveCriteria is the minimum set of criteria to watch the
// items in patterns
func EffectiveCriteria(globs ...string) (*WatchCriteria, error) {
if len(globs) == 0 {
return nil, nil
}
result := newWatchCriteria()
for _, glob := range globs {
err := result.add(glob)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
}
return result, nil
}