@@ -1,8 +1,12 @@
11package fsext
22
33import (
4+ "bytes"
5+ "io"
6+ "log/slog"
47 "os"
58 "path/filepath"
9+ "strings"
610
711 "github.com/charlievieth/fastwalk"
812 ignore "github.com/sabhiram/go-gitignore"
@@ -67,10 +71,8 @@ var CommonIgnorePatterns = []string{
6771}
6872
6973type DirectoryLister struct {
70− gitignore *ignore.GitIgnore
71− crushignore *ignore.GitIgnore
72− commonIgnore *ignore.GitIgnore
73− rootPath string
74+ ignores *ignore.GitIgnore
75+ rootPath string
7476}
7577
7678func NewDirectoryLister(rootPath string) *DirectoryLister {
@@ -78,26 +80,29 @@ func NewDirectoryLister(rootPath string) *DirectoryLister {
7880 rootPath: rootPath,
7981 }
8082
81− // Load gitignore if it exists
82− gitignorePath := filepath.Join(rootPath, ".gitignore")
83− if _, err := os.Stat(gitignorePath); err == nil {
84− if gi, err := ignore.CompileIgnoreFile(gitignorePath); err == nil {
85− dl.gitignore = gi
86− }
87− }
83+ dl.ignores = ignore.CompileIgnoreLines(append(CommonIgnorePatterns, strings.Split(parseIgnores(rootPath), "\n")...)...)
84+
85+ return dl
86+}
8887
89− // Load crushignore if it exists
90− crushignorePath := filepath.Join(rootPath, ".crushignore")
91− if _, err := os.Stat(crushignorePath); err == nil {
92− if ci, err := ignore.CompileIgnoreFile(crushignorePath); err == nil {
93− dl.crushignore = ci
88+func parseIgnores(path string) string {
89+ var b bytes.Buffer
90+ for _, ign := range []string{".crushignore", ".gitignore"} {
91+ p := filepath.Join(path, ign)
92+ if _, err := os.Stat(p); err == nil {
93+ f, err := os.Open(p)
94+ if err != nil {
95+ _ = f.Close()
96+ slog.Error("Failed to open ignore file", "path", p, "error", err)
97+ continue
98+ }
99+ if _, err := io.Copy(&b, f); err != nil {
100+ slog.Error("Failed to read ignore file", "path", p, "error", err)
101+ }
102+ _ = f.Close()
94103 }
95104 }
96−
97− // Create common ignore patterns
98− dl.commonIgnore = ignore.CompileIgnoreLines(CommonIgnorePatterns...)
99−
100− return dl
105+ return b.String()
101106}
102107
103108func (dl *DirectoryLister) shouldIgnore(path string, ignorePatterns []string) bool {
@@ -106,18 +111,7 @@ func (dl *DirectoryLister) shouldIgnore(path string, ignorePatterns []string) bo
106111 relPath = path
107112 }
108113
109− // Check common ignore patterns
110− if dl.commonIgnore.MatchesPath(relPath) {
111− return true
112− }
113−
114− // Check gitignore patterns if available
115− if dl.gitignore != nil && dl.gitignore.MatchesPath(relPath) {
116− return true
117− }
118−
119− // Check crushignore patterns if available
120− if dl.crushignore != nil && dl.crushignore.MatchesPath(relPath) {
114+ if dl.ignores.MatchesPath(relPath) {
121115 return true
122116 }
123117
@@ -144,6 +138,7 @@ func ListDirectory(initialPath string, ignorePatterns []string, limit int) ([]st
144138 ToSlash: fastwalk.DefaultToSlash(),
145139 Sort: fastwalk.SortDirsFirst,
146140 }
141+
147142 err := fastwalk.Walk(&conf, initialPath, func(path string, d os.DirEntry, err error) error {
148143 if err != nil {
149144 return nil // Skip files we don't have permission to access