From 0830c5ceb1bb51fb877c5fff9a78f6022c5ab3e9 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/rules.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/internal/ignore/rules.go b/internal/ignore/rules.go index a80923baf0c..a5212d317e1 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.