on main help sign in
feat: support .crushignore as well as .gitignore
5a6329cCarlos Alexandro Becker
internal/fsext/fileutil.go+24−3
@@ -107,8 +107,9 @@ func SkipHidden(path string) bool {
107
107
108// FastGlobWalker provides gitignore-aware file walking with fastwalk
108// FastGlobWalker provides gitignore-aware file walking with fastwalk
109type FastGlobWalker struct {
109type FastGlobWalker struct {
110+ gitignore *ignore.GitIgnore
110− gitignore *ignore.GitIgnore
111+ crushignore *ignore.GitIgnore
111− rootPath string
112+ rootPath string
112}
113}
113
114
114func NewFastGlobWalker(searchPath string) *FastGlobWalker {
115func NewFastGlobWalker(searchPath string) *FastGlobWalker {
@@ -124,6 +125,14 @@ func NewFastGlobWalker(searchPath string) *FastGlobWalker {
124 }
125 }
125 }
126 }
126
127
128+ // Load crushignore if it exists
129+ crushignorePath := filepath.Join(searchPath, ".crushignore")
130+ if _, err := os.Stat(crushignorePath); err == nil {
131+ if ci, err := ignore.CompileIgnoreFile(crushignorePath); err == nil {
132+ walker.crushignore = ci
133+ }
134+ }
135+
127 return walker
136 return walker
128}
137}
129
138
@@ -132,13 +141,25 @@ func (w *FastGlobWalker) shouldSkip(path string) bool {
132 return true
141 return true
133 }
142 }
134
143
144+ relPath, err := filepath.Rel(w.rootPath, path)
145+ if err != nil {
146+ relPath = path
147+ }
148+
149+ // Check gitignore patterns if available
135 if w.gitignore != nil {
150 if w.gitignore != nil {
136− relPath, err := filepath.Rel(w.rootPath, path)
137 if err == nil && w.gitignore.MatchesPath(relPath) {
151 if err == nil && w.gitignore.MatchesPath(relPath) {
138 return true
152 return true
139 }
153 }
140 }
154 }
141
155
156+ // Check crushignore patterns if available
157+ if w.crushignore != nil {
158+ if err == nil && w.crushignore.MatchesPath(relPath) {
159+ return true
160+ }
161+ }
162+
142 return false
163 return false
143}
164}
144
165
internal/fsext/ignore_test.gonew file+44
@@ -0,0 +1,44 @@
1+package fsext
2+
3+import (
4+ "os"
5+ "testing"
6+
7+ "github.com/stretchr/testify/require"
8+)
9+
10+func TestCrushIgnore(t *testing.T) {
11+ // Create a temporary directory for testing
12+ tempDir := t.TempDir()
13+
14+ // Change to temp directory
15+ oldWd, _ := os.Getwd()
16+ err := os.Chdir(tempDir)
17+ require.NoError(t, err)
18+ defer os.Chdir(oldWd)
19+
20+ // Create test files
21+ require.NoError(t, os.WriteFile("test1.txt", []byte("test"), 0644))
22+ require.NoError(t, os.WriteFile("test2.log", []byte("test"), 0644))
23+ require.NoError(t, os.WriteFile("test3.tmp", []byte("test"), 0644))
24+
25+ // Create a .crushignore file that ignores .log files
26+ require.NoError(t, os.WriteFile(".crushignore", []byte("*.log\n"), 0644))
27+
28+ // Test DirectoryLister
29+ t.Run("DirectoryLister respects .crushignore", func(t *testing.T) {
30+ dl := NewDirectoryLister(tempDir)
31+
32+ // Test that .log files are ignored
33+ require.True(t, dl.gitignore == nil, "gitignore should be nil")
34+ require.NotNil(t, dl.crushignore, "crushignore should not be nil")
35+ })
36+
37+ // Test FastGlobWalker
38+ t.Run("FastGlobWalker respects .crushignore", func(t *testing.T) {
39+ walker := NewFastGlobWalker(tempDir)
40+
41+ require.True(t, walker.gitignore == nil, "gitignore should be nil")
42+ require.NotNil(t, walker.crushignore, "crushignore should not be nil")
43+ })
44+}
internal/fsext/ls.go+14
@@ -68,6 +68,7 @@ var CommonIgnorePatterns = []string{
68
68
69type DirectoryLister struct {
69type DirectoryLister struct {
70 gitignore *ignore.GitIgnore
70 gitignore *ignore.GitIgnore
71+ crushignore *ignore.GitIgnore
71 commonIgnore *ignore.GitIgnore
72 commonIgnore *ignore.GitIgnore
72 rootPath string
73 rootPath string
73}
74}
@@ -85,6 +86,14 @@ func NewDirectoryLister(rootPath string) *DirectoryLister {
85 }
86 }
86 }
87 }
87
88
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
94+ }
95+ }
96+
88 // Create common ignore patterns
97 // Create common ignore patterns
89 dl.commonIgnore = ignore.CompileIgnoreLines(CommonIgnorePatterns...)
98 dl.commonIgnore = ignore.CompileIgnoreLines(CommonIgnorePatterns...)
90
99
@@ -107,6 +116,11 @@ func (dl *DirectoryLister) shouldIgnore(path string, ignorePatterns []string) bo
107 return true
116 return true
108 }
117 }
109
118
119+ // Check crushignore patterns if available
120+ if dl.crushignore != nil && dl.crushignore.MatchesPath(relPath) {
121+ return true
122+ }
123+
110 base := filepath.Base(path)
124 base := filepath.Base(path)
111
125
112 for _, pattern := range ignorePatterns {
126 for _, pattern := range ignorePatterns {