act/vendor/gopkg.in/godo.v2/glob/watchCriteria.go

165 lines
3.3 KiB
Go
Raw Normal View History

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
}