|
@@ -61,12 +61,56 @@ func NewPatternMatcher(patterns []string) (*PatternMatcher, error) {
|
|
|
// The "file" argument should be a slash-delimited path.
|
|
|
//
|
|
|
// Matches is not safe to call concurrently.
|
|
|
+//
|
|
|
+// This implementation is buggy (it only checks a single parent dir against the
|
|
|
+// pattern) and will be removed soon. Use either MatchesOrParentMatches or
|
|
|
+// MatchesUsingParentResult instead.
|
|
|
func (pm *PatternMatcher) Matches(file string) (bool, error) {
|
|
|
matched := false
|
|
|
file = filepath.FromSlash(file)
|
|
|
parentPath := filepath.Dir(file)
|
|
|
parentPathDirs := strings.Split(parentPath, string(os.PathSeparator))
|
|
|
|
|
|
+ for _, pattern := range pm.patterns {
|
|
|
+ // Skip evaluation if this is an inclusion and the filename
|
|
|
+ // already matched the pattern, or it's an exclusion and it has
|
|
|
+ // not matched the pattern yet.
|
|
|
+ if pattern.exclusion != matched {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ match, err := pattern.match(file)
|
|
|
+ if err != nil {
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !match && parentPath != "." {
|
|
|
+ // Check to see if the pattern matches one of our parent dirs.
|
|
|
+ if len(pattern.dirs) <= len(parentPathDirs) {
|
|
|
+ match, _ = pattern.match(strings.Join(parentPathDirs[:len(pattern.dirs)], string(os.PathSeparator)))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if match {
|
|
|
+ matched = !pattern.exclusion
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return matched, nil
|
|
|
+}
|
|
|
+
|
|
|
+// MatchesOrParentMatches returns true if "file" matches any of the patterns
|
|
|
+// and isn't excluded by any of the subsequent patterns.
|
|
|
+//
|
|
|
+// The "file" argument should be a slash-delimited path.
|
|
|
+//
|
|
|
+// Matches is not safe to call concurrently.
|
|
|
+func (pm *PatternMatcher) MatchesOrParentMatches(file string) (bool, error) {
|
|
|
+ matched := false
|
|
|
+ file = filepath.FromSlash(file)
|
|
|
+ parentPath := filepath.Dir(file)
|
|
|
+ parentPathDirs := strings.Split(parentPath, string(os.PathSeparator))
|
|
|
+
|
|
|
for _, pattern := range pm.patterns {
|
|
|
// Skip evaluation if this is an inclusion and the filename
|
|
|
// already matched the pattern, or it's an exclusion and it has
|
|
@@ -249,6 +293,9 @@ func (p *Pattern) compile() error {
|
|
|
|
|
|
// Matches returns true if file matches any of the patterns
|
|
|
// and isn't excluded by any of the subsequent patterns.
|
|
|
+//
|
|
|
+// This implementation is buggy (it only checks a single parent dir against the
|
|
|
+// pattern) and will be removed soon. Use MatchesOrParentMatches instead.
|
|
|
func Matches(file string, patterns []string) (bool, error) {
|
|
|
pm, err := NewPatternMatcher(patterns)
|
|
|
if err != nil {
|
|
@@ -264,6 +311,23 @@ func Matches(file string, patterns []string) (bool, error) {
|
|
|
return pm.Matches(file)
|
|
|
}
|
|
|
|
|
|
+// MatchesOrParentMatches returns true if file matches any of the patterns
|
|
|
+// and isn't excluded by any of the subsequent patterns.
|
|
|
+func MatchesOrParentMatches(file string, patterns []string) (bool, error) {
|
|
|
+ pm, err := NewPatternMatcher(patterns)
|
|
|
+ if err != nil {
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ file = filepath.Clean(file)
|
|
|
+
|
|
|
+ if file == "." {
|
|
|
+ // Don't let them exclude everything, kind of silly.
|
|
|
+ return false, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return pm.MatchesOrParentMatches(file)
|
|
|
+}
|
|
|
+
|
|
|
// CopyFile copies from src to dst until either EOF is reached
|
|
|
// on src or an error occurs. It verifies src exists and removes
|
|
|
// the dst if it exists.
|