From 04d3dbf2dd1fd91d918e7558bb0fd8947abc7a17 Mon Sep 17 00:00:00 2001 From: Talia Stocks <928827+taliastocks@users.noreply.github.com> Date: Fri, 29 Oct 2021 17:00:23 -0400 Subject: [PATCH] [helmignore] Support for '!' as a special leading sequence .helmignore has "supported" negative matches uselessly for a long time, reported as an open ticket (https://github.com/helm/helm/issues/3622) as early as 2018. This revision implements negative matching correctly and usefully for the first time. Signed-off-by: Talia Stocks --- internal/ignore/doc.go | 1 - internal/ignore/rules.go | 23 ++++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/internal/ignore/doc.go b/internal/ignore/doc.go index e6a6a6c7b..61843bfa8 100644 --- a/internal/ignore/doc.go +++ b/internal/ignore/doc.go @@ -62,6 +62,5 @@ Notable differences from .gitignore: - The globbing library is Go's 'filepath.Match', not fnmatch(3) - Trailing spaces are always ignored (there is no supported escape sequence) - The evaluation of escape sequences has not been tested for compatibility - - There is no support for '\!' as a special leading sequence. */ package ignore // import "helm.sh/helm/v3/internal/ignore" diff --git a/internal/ignore/rules.go b/internal/ignore/rules.go index a80923baf..1aff885fd 100644 --- a/internal/ignore/rules.go +++ b/internal/ignore/rules.go @@ -100,22 +100,30 @@ func (r *Rules) Ignore(path string, fi os.FileInfo) bool { if path == "." || path == "./" { return false } + + // Negative rules should only override positive ignore rules, rather + // than exclude everything aside from the pattern (e.g. Chart.yaml). + // See issue: + // 3622 Whitelisting in .helmignore with '/*' returns "chart metadata (Chart.yaml) missing" + positiveMatch := false + negativeMatch := false + for _, p := range r.patterns { if p.match == nil { log.Printf("ignore: no matcher supplied for %q", p.raw) return false } - // For negative rules, we need to capture and return non-matches, - // and continue for matches. + // For negative rules, we need to continue for non-matches, + // and record matches. if p.negate { if p.mustDir && !fi.IsDir() { - return true + continue } if !p.match(path, fi) { - return true + continue } - continue + negativeMatch = true } // If the rule is looking for directories, and this is not a directory, @@ -124,10 +132,11 @@ func (r *Rules) Ignore(path string, fi os.FileInfo) bool { continue } if p.match(path, fi) { - return true + positiveMatch = true } } - return false + + return positiveMatch && !negativeMatch } // parseRule parses a rule string and creates a pattern, which is then stored in the Rules object.