package scanner import ( "os" "path/filepath" "strings" ) // IncludePatterns are patterns for env files to include var IncludePatterns = []string{ ".env", ".env.*", "*.env", } // ExcludeFiles are specific filenames to exclude var ExcludeFiles = []string{ ".env.example", ".env.sample", ".env.template", } // ExcludeDirs are directories to skip when scanning var ExcludeDirs = []string{ "node_modules", ".git", "vendor", "venv", ".venv", "__pycache__", ".idea", ".vscode", "dist", "build", } // Scan recursively scans the directory for env files func Scan(rootDir string) ([]string, error) { var envFiles []string err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } // Skip excluded directories if info.IsDir() { for _, excludeDir := range ExcludeDirs { if info.Name() == excludeDir { return filepath.SkipDir } } return nil } // Check if file should be excluded for _, excludeFile := range ExcludeFiles { if info.Name() == excludeFile { return nil } } // Check if file matches include patterns if matchesPattern(info.Name()) { // Get relative path from rootDir relPath, err := filepath.Rel(rootDir, path) if err != nil { return err } envFiles = append(envFiles, relPath) } return nil }) if err != nil { return nil, err } return envFiles, nil } // matchesPattern checks if filename matches any include pattern func matchesPattern(filename string) bool { // Pattern: .env (exact match) if filename == ".env" { return true } // Pattern: .env.* (e.g., .env.production, .env.local) if strings.HasPrefix(filename, ".env.") { return true } // Pattern: *.env (e.g., docker.env, app.env) if strings.HasSuffix(filename, ".env") && filename != ".env" { return true } return false }