From 89cf1baf1764bcd097e600825cafdf521125da90 Mon Sep 17 00:00:00 2001 From: Omri SirComp Date: Tue, 26 May 2026 08:21:54 +0300 Subject: [PATCH] fix(analyzer): cache resolved exclude paths --- pkg/analyzer/analyzer.go | 26 +++++++++++++++++++------- pkg/analyzer/analyzer_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index 83ac9f8a359..ca4265314d4 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -338,6 +338,7 @@ func Analyze(a *Analyzer) (model.AnalyzedPaths, error) { projectConfigFiles := make([]string, 0) done := make(chan bool) hasGitIgnoreFile, gitIgnore := shouldConsiderGitIgnoreFile(a.Paths[0], a.GitIgnoreFileName, a.ExcludeGitIgnore) + excludedFiles := resolveExcludedFiles(a.Exc) // get all the files inside the given paths for _, path := range a.Paths { if _, err := os.Stat(path); err != nil { @@ -351,14 +352,19 @@ func Analyze(a *Analyzer) (model.AnalyzedPaths, error) { ext, errExt := utils.GetExtension(path) if errExt == nil { trimmedPath := strings.ReplaceAll(path, a.Paths[0], filepath.Base(a.Paths[0])) + ignoreFilesLen := len(ignoreFiles) ignoreFiles = a.checkIgnore(info.Size(), hasGitIgnoreFile, gitIgnore, path, trimmedPath, ignoreFiles) + if len(ignoreFiles) > ignoreFilesLen { + excludedFiles[path] = struct{}{} + } if isConfigFile(path, defaultConfigFiles) { projectConfigFiles = append(projectConfigFiles, path) a.Exc = append(a.Exc, path) + excludedFiles[path] = struct{}{} } - if _, ok := possibleFileTypes[ext]; ok && !isExcludedFile(path, a.Exc) { + if _, ok := possibleFileTypes[ext]; ok && !isExcludedFile(path, excludedFiles) { files = append(files, path) } } @@ -782,20 +788,26 @@ func getKeysFromExcludeTypesFlag(excludeTypesFlag []string) []string { return ks } -// isExcludedFile verifies if the path is pointed in the --exclude-paths flag -func isExcludedFile(path string, exc []string) bool { +func resolveExcludedFiles(exc []string) map[string]struct{} { + excludedFiles := make(map[string]struct{}) for i := range exc { exclude, err := provider.GetExcludePaths(exc[i]) if err != nil { log.Err(err).Msg("failed to get exclude paths") } for j := range exclude { - if exclude[j] == path { - log.Info().Msgf("Excluded file %s from analyzer", path) - return true - } + excludedFiles[exclude[j]] = struct{}{} } } + return excludedFiles +} + +// isExcludedFile verifies if the path is pointed in the --exclude-paths flag +func isExcludedFile(path string, excludedFiles map[string]struct{}) bool { + if _, ok := excludedFiles[path]; ok { + log.Info().Msgf("Excluded file %s from analyzer", path) + return true + } return false } diff --git a/pkg/analyzer/analyzer_test.go b/pkg/analyzer/analyzer_test.go index ea7adcf7f69..9fa2c8d3a4b 100644 --- a/pkg/analyzer/analyzer_test.go +++ b/pkg/analyzer/analyzer_test.go @@ -1,6 +1,7 @@ package analyzer import ( + "os" "path/filepath" "sort" "testing" @@ -729,6 +730,33 @@ func TestAnalyzer_FileStats(t *testing.T) { } } +func TestAnalyzer_AnalyzeWithGlobExclude(t *testing.T) { + tempDir := t.TempDir() + + err := os.MkdirAll(filepath.Join(tempDir, "nested", "excluded"), 0755) + require.NoError(t, err) + err = os.MkdirAll(filepath.Join(tempDir, "nested", "included"), 0755) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(tempDir, "nested", "excluded", "main.tf"), []byte("resource \"aws_s3_bucket\" \"excluded\" {}\n"), 0644) + require.NoError(t, err) + err = os.WriteFile(filepath.Join(tempDir, "nested", "included", "main.tf"), []byte("resource \"aws_s3_bucket\" \"included\" {}\n"), 0644) + require.NoError(t, err) + + analyzer := &Analyzer{ + Paths: []string{tempDir}, + Types: []string{""}, + ExcludeTypes: []string{""}, + Exc: []string{filepath.Join(tempDir, "**", "excluded", "*.tf")}, + MaxFileSize: -1, + } + + got, err := Analyze(analyzer) + require.NoError(t, err) + + require.Contains(t, got.Types, "terraform") + require.Equal(t, 1, got.FileStats["terraform"].FileCount) +} + type platformFileStats struct { fileCount int dirCount int