diff --git a/pkg/healthcheck/nonascii.go b/pkg/healthcheck/nonascii.go index c652377..560573e 100644 --- a/pkg/healthcheck/nonascii.go +++ b/pkg/healthcheck/nonascii.go @@ -9,9 +9,43 @@ import ( "strings" "unicode" + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/format/gitattributes" ) +// getSubmodulePathsFromGoGit uses the go-git library to open the repository +// at the given root path and retrieve a list of all submodule paths. +// It returns a set of submodule paths for efficient lookup. +func getSubmodulePathsFromGoGit(root string) (map[string]struct{}, error) { + submodulePaths := make(map[string]struct{}) + + // Open the git repository at the given path. + repo, err := git.PlainOpen(root) + if err != nil { + if err == git.ErrRepositoryNotExists { + return submodulePaths, nil + } + return nil, fmt.Errorf("error opening git repository: %w", err) + } + + worktree, err := repo.Worktree() + if err != nil { + return nil, fmt.Errorf("error getting worktree: %w", err) + } + + // Get the list of submodules. + submodules, err := worktree.Submodules() + if err != nil { + return nil, fmt.Errorf("error getting submodules: %w", err) + } + + for _, sm := range submodules { + submodulePaths[filepath.ToSlash(sm.Config().Path)] = struct{}{} + } + + return submodulePaths, nil +} + // getNonASCII retrieves a list of files in the specified root directory that contain non-ASCII characters. // It searches for non-ASCII characters in each file's content and returns a list of paths to files containing non-ASCII characters. func getNonASCII(root string) ([]string, error) { @@ -23,6 +57,11 @@ func getNonASCII(root string) ([]string, error) { gitattrExist = false } + submodules, err := getSubmodulePathsFromGoGit(root) + if err != nil { + return nil, err + } + if gitattrExist { fs := os.DirFS(".") f, err := fs.Open(".gitattributes") @@ -42,18 +81,22 @@ func getNonASCII(root string) ([]string, error) { return err } + relPath, err := filepath.Rel(root, path) + if err != nil { + return err + } + if info.IsDir() { if info.Name() == ".git" { return filepath.SkipDir } + if _, isSubmodule := submodules[relPath]; isSubmodule { + return filepath.SkipDir + } return nil } if gitattrExist { - relPath, err := filepath.Rel(root, path) - if err != nil { - return err - } ret, matched := matcher.Match(strings.Split(relPath, "/"), nil) if matched && ret["text"].IsUnset() && !ret["text"].IsSet() { return nil