Przeglądaj źródła

Rename Matches to MatchesOrParentMatches

Signed-off-by: Aaron Lehmann <alehmann@netflix.com>
Aaron Lehmann 3 lat temu
rodzic
commit
97ede9df26

+ 1 - 1
builder/remotecontext/detect.go

@@ -130,7 +130,7 @@ func removeDockerfile(c modifiableContext, filesToRemove ...string) error {
 	f.Close()
 	filesToRemove = append([]string{".dockerignore"}, filesToRemove...)
 	for _, fileToRemove := range filesToRemove {
-		if rm, _ := fileutils.Matches(fileToRemove, excludes); rm {
+		if rm, _ := fileutils.MatchesOrParentMatches(fileToRemove, excludes); rm {
 			if err := c.Remove(fileToRemove); err != nil {
 				logrus.Errorf("failed to remove %s: %v", fileToRemove, err)
 			}

+ 1 - 1
pkg/archive/archive.go

@@ -860,7 +860,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
 					if len(parentMatched) != 0 {
 						skip, err = pm.MatchesUsingParentResult(relFilePath, parentMatched[len(parentMatched)-1])
 					} else {
-						skip, err = pm.Matches(relFilePath)
+						skip, err = pm.MatchesOrParentMatches(relFilePath)
 					}
 					if err != nil {
 						logrus.Errorf("Error matching %s: %v", relFilePath, err)

+ 64 - 0
pkg/fileutils/fileutils.go

@@ -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.

+ 2 - 2
pkg/fileutils/fileutils_test.go

@@ -382,12 +382,12 @@ func TestMatches(t *testing.T) {
 		}...)
 	}
 
-	t.Run("Matches", func(t *testing.T) {
+	t.Run("MatchesOrParentMatches", func(t *testing.T) {
 		for _, test := range tests {
 			desc := fmt.Sprintf("pattern=%q text=%q", test.pattern, test.text)
 			pm, err := NewPatternMatcher([]string{test.pattern})
 			assert.NilError(t, err, desc)
-			res, _ := pm.Matches(test.text)
+			res, _ := pm.MatchesOrParentMatches(test.text)
 			assert.Check(t, is.Equal(test.pass, res), desc)
 		}
 	})