From 26200a57717c1631e252e126d04bfa1d8e15b59c Mon Sep 17 00:00:00 2001 From: AntonDebricked Date: Tue, 9 Jul 2024 15:03:02 +0200 Subject: [PATCH] log cases where no manifest or lock files were found. Provides details as to why no files were found. --- internal/file/finder.go | 85 ++++++++++++++++++++++++++++++------ internal/file/finder_test.go | 81 ++++++++++++++++++++++++++++++++++ internal/file/groups.go | 9 ++++ 3 files changed, 162 insertions(+), 13 deletions(-) diff --git a/internal/file/finder.go b/internal/file/finder.go index 982decef..09e73530 100644 --- a/internal/file/finder.go +++ b/internal/file/finder.go @@ -77,28 +77,47 @@ func (finder *Finder) GetConfigPath(rootPath string, exclusions []string, inclus return configPath } -// GetGroups return all file groups in specified path recursively. -func (finder *Finder) GetGroups(options DebrickedOptions) (Groups, error) { +func (finder *Finder) GetIncludedGroups(formats []*CompiledFormat, options DebrickedOptions) (Groups, error) { + // NOTE: inefficient because it walks into excluded directories var groups Groups + err := filepath.Walk( + options.RootPath, + func(path string, fileInfo os.FileInfo, err error) error { + if err != nil { + return err + } + var excluded = Excluded(options.Exclusions, options.Inclusions, path) - formats, err := finder.GetSupportedFormats() - if err != nil { - return groups, err - } - if len(options.RootPath) == 0 { - options.RootPath = filepath.Base("") - } + if !fileInfo.IsDir() && !excluded { + for _, format := range formats { + if groups.Match(format, path, options.LockFileOnly) { - // Traverse files to find dependency file groups - err = filepath.Walk( + break + } + } + } + + return nil + }, + ) + + return groups, err +} + +func (finder *Finder) GetExcludedGroups(formats []*CompiledFormat, options DebrickedOptions) (Groups, []string, error) { + var excludedGroups Groups + var excludedFiles []string + err := filepath.Walk( options.RootPath, func(path string, fileInfo os.FileInfo, err error) error { if err != nil { + return err } - if !fileInfo.IsDir() && !Excluded(options.Exclusions, options.Inclusions, path) { + if !fileInfo.IsDir() { for _, format := range formats { - if groups.Match(format, path, options.LockFileOnly) { + if excludedGroups.Match(format, path, options.LockFileOnly) { + excludedFiles = append(excludedFiles, path) break } @@ -109,6 +128,46 @@ func (finder *Finder) GetGroups(options DebrickedOptions) (Groups, error) { }, ) + return excludedGroups, excludedFiles, err +} + +// GetGroups return all file groups in specified path recursively. +func (finder *Finder) GetGroups(options DebrickedOptions) (Groups, error) { + var groups Groups + var noGroupsFound bool + + formats, err := finder.GetSupportedFormats() + if err != nil { + + return groups, err + } + if len(options.RootPath) == 0 { + options.RootPath = filepath.Base("") + } + + // Traverse files to find dependency file groups + groups, err = finder.GetIncludedGroups(formats, options) + noGroupsFound = len(groups.groups) == 0 + if noGroupsFound { + // No dependencies found. (should rarely happen) + // Traverse again to see if dependency files were excluded. + _, excludedFiles, excludedErr := finder.GetExcludedGroups(formats, options) + if len(excludedFiles) > 0 { + fmt.Println("The following files were excluded, resulting in no dependency files found.") + for _, file := range excludedFiles { + fmt.Println(file) + } + fmt.Println("Please change the inclusion and exclusion options if an important file or directory was missed.") + } else { + fmt.Println("No dependency file matches found with current configuration.") + fmt.Println("Please change the inclusion and exclusion options if an important file or directory was missed.") + } + if excludedErr != nil { + + return groups, err + } + } + groups.FilterGroupsByStrictness(options.Strictness) return groups, err diff --git a/internal/file/finder_test.go b/internal/file/finder_test.go index d61e8c58..465b00bf 100644 --- a/internal/file/finder_test.go +++ b/internal/file/finder_test.go @@ -3,8 +3,10 @@ package file import ( "bytes" "encoding/json" + "fmt" "io" "net/http" + "os" "path" "path/filepath" "sort" @@ -185,6 +187,85 @@ func TestGetGroupsPIP(t *testing.T) { } +func CaptureStdout(function func(options DebrickedOptions) (Groups, error), options DebrickedOptions) string { + oldStdout := os.Stdout + read, write, _ := os.Pipe() + os.Stdout = write + + _, err := function(options) + if err != nil { + fmt.Printf("Error: %v\n", err) + + return "" + } + + write.Close() + os.Stdout = oldStdout + var buf bytes.Buffer + _, err = io.Copy(&buf, read) + if err != nil { + fmt.Printf("Error: %v\n", err) + + return "" + } + + return buf.String() +} + +func TestGetGroupsAllExcluded(t *testing.T) { + setUp(true) + + options := DebrickedOptions{ + RootPath: "testdata/misc", + Exclusions: []string{"**/**"}, + Inclusions: []string{}, + LockFileOnly: false, + Strictness: StrictAll, + } + actualOutput := CaptureStdout(finder.GetGroups, options) + + // Define the expected output + expectedStart := "The following files were excluded, resulting in no dependency files found." + expectedEnd := "Please change the inclusion and exclusion options if an important file or directory was missed." + expectedExcludedFile := "requirements.txt" + + // Compare the actual output to the expected output + if !strings.Contains(actualOutput, expectedStart) { + t.Errorf("Expected %q but got %q", expectedStart, actualOutput) + } + if !strings.Contains(actualOutput, expectedEnd) { + t.Errorf("Expected %q but got %q", expectedEnd, actualOutput) + } + if !strings.Contains(actualOutput, expectedExcludedFile) { + t.Errorf("Expected %q but got %q", expectedExcludedFile, actualOutput) + } +} + +func TestGetGroupsAllExcludedByStrictness(t *testing.T) { + setUp(true) + + options := DebrickedOptions{ + RootPath: "testdata/misc", + Exclusions: []string{"**/composer.**"}, //the only manifest+lock pair in testdata/misc + Inclusions: []string{}, + LockFileOnly: false, + Strictness: StrictPairs, + } + actualOutput := CaptureStdout(finder.GetGroups, options) + + // Define the expected output + expectedStart := "The following files and directories were filtered out by strictness flag, resulting in no file matches." + expectedEnd := "Please change the inclusion and exclusion options if an important file or directory was missed." + + // Compare the actual output to the expected output + if !strings.Contains(actualOutput, expectedStart) { + t.Errorf("Expected %q but got %q", expectedStart, actualOutput) + } + if !strings.Contains(actualOutput, expectedEnd) { + t.Errorf("Expected %q but got %q", expectedEnd, actualOutput) + } +} + func TestGetGroupsWithOnlyLockFiles(t *testing.T) { setUp(true) path := "testdata/misc" diff --git a/internal/file/groups.go b/internal/file/groups.go index 328fa4be..0686e041 100644 --- a/internal/file/groups.go +++ b/internal/file/groups.go @@ -1,6 +1,7 @@ package file import ( + "fmt" "path/filepath" ) @@ -79,6 +80,14 @@ func (gs *Groups) FilterGroupsByStrictness(strictness int) { } } + if len(groups) == 0 && len(gs.groups) > 0 { + fmt.Println("The following files and directories were filtered out by strictness flag, resulting in no file matches.") + for _, group := range gs.groups { + fmt.Println(group.GetAllFiles()) + } + fmt.Println("Please change the inclusion and exclusion options if an important file or directory was missed.") + } + gs.groups = groups }