10 "github.com/stretchr/testify/require"
13func TestGlobWithDoubleStar(t *testing.T) {
14 t.Run("finds files matching pattern", func(t *testing.T) {
15 testDir := t.TempDir()
17 mainGo := filepath.Join(testDir, "src", "main.go")
18 utilsGo := filepath.Join(testDir, "src", "utils.go")
19 helperGo := filepath.Join(testDir, "pkg", "helper.go")
20 readmeMd := filepath.Join(testDir, "README.md")
22 for _, file := range []string{mainGo, utilsGo, helperGo, readmeMd} {
23 require.NoError(t, os.MkdirAll(filepath.Dir(file), 0o755))
24 require.NoError(t, os.WriteFile(file, []byte("test content"), 0o644))
27 matches, truncated, err := GlobWithDoubleStar("**/main.go", testDir, 0)
28 require.NoError(t, err)
29 require.False(t, truncated)
31 require.Equal(t, matches, []string{mainGo})
34 t.Run("finds directories matching pattern", func(t *testing.T) {
35 testDir := t.TempDir()
37 srcDir := filepath.Join(testDir, "src")
38 pkgDir := filepath.Join(testDir, "pkg")
39 internalDir := filepath.Join(testDir, "internal")
40 cmdDir := filepath.Join(testDir, "cmd")
41 pkgFile := filepath.Join(testDir, "pkg.txt")
43 for _, dir := range []string{srcDir, pkgDir, internalDir, cmdDir} {
44 require.NoError(t, os.MkdirAll(dir, 0o755))
47 require.NoError(t, os.WriteFile(filepath.Join(srcDir, "main.go"), []byte("package main"), 0o644))
48 require.NoError(t, os.WriteFile(pkgFile, []byte("test"), 0o644))
50 matches, truncated, err := GlobWithDoubleStar("pkg", testDir, 0)
51 require.NoError(t, err)
52 require.False(t, truncated)
54 require.Equal(t, matches, []string{pkgDir})
57 t.Run("finds nested directories with wildcard patterns", func(t *testing.T) {
58 testDir := t.TempDir()
60 srcPkgDir := filepath.Join(testDir, "src", "pkg")
61 libPkgDir := filepath.Join(testDir, "lib", "pkg")
62 mainPkgDir := filepath.Join(testDir, "pkg")
63 otherDir := filepath.Join(testDir, "other")
65 for _, dir := range []string{srcPkgDir, libPkgDir, mainPkgDir, otherDir} {
66 require.NoError(t, os.MkdirAll(dir, 0o755))
69 matches, truncated, err := GlobWithDoubleStar("**/pkg", testDir, 0)
70 require.NoError(t, err)
71 require.False(t, truncated)
73 var relativeMatches []string
74 for _, match := range matches {
75 rel, err := filepath.Rel(testDir, match)
76 require.NoError(t, err)
77 relativeMatches = append(relativeMatches, filepath.ToSlash(rel))
80 require.ElementsMatch(t, relativeMatches, []string{"pkg", "src/pkg", "lib/pkg"})
83 t.Run("finds directory contents with recursive patterns", func(t *testing.T) {
84 testDir := t.TempDir()
86 pkgDir := filepath.Join(testDir, "pkg")
87 pkgFile1 := filepath.Join(pkgDir, "main.go")
88 pkgFile2 := filepath.Join(pkgDir, "utils.go")
89 pkgSubdir := filepath.Join(pkgDir, "internal")
90 pkgSubfile := filepath.Join(pkgSubdir, "helper.go")
92 require.NoError(t, os.MkdirAll(pkgSubdir, 0o755))
94 for _, file := range []string{pkgFile1, pkgFile2, pkgSubfile} {
95 require.NoError(t, os.WriteFile(file, []byte("package main"), 0o644))
98 matches, truncated, err := GlobWithDoubleStar("pkg/**", testDir, 0)
99 require.NoError(t, err)
100 require.False(t, truncated)
102 var relativeMatches []string
103 for _, match := range matches {
104 rel, err := filepath.Rel(testDir, match)
105 require.NoError(t, err)
106 relativeMatches = append(relativeMatches, filepath.ToSlash(rel))
109 require.ElementsMatch(t, relativeMatches, []string{
114 "pkg/internal/helper.go",
118 t.Run("respects limit parameter", func(t *testing.T) {
119 testDir := t.TempDir()
122 file := filepath.Join(testDir, "file", fmt.Sprintf("test%d.txt", i))
123 require.NoError(t, os.MkdirAll(filepath.Dir(file), 0o755))
124 require.NoError(t, os.WriteFile(file, []byte("test"), 0o644))
127 matches, truncated, err := GlobWithDoubleStar("**/*.txt", testDir, 5)
128 require.NoError(t, err)
129 require.True(t, truncated, "Expected truncation with limit")
130 require.Len(t, matches, 5, "Expected exactly 5 matches with limit")
133 t.Run("handles nested directory patterns", func(t *testing.T) {
134 testDir := t.TempDir()
136 file1 := filepath.Join(testDir, "a", "b", "c", "file1.txt")
137 file2 := filepath.Join(testDir, "a", "b", "file2.txt")
138 file3 := filepath.Join(testDir, "a", "file3.txt")
139 file4 := filepath.Join(testDir, "file4.txt")
141 for _, file := range []string{file1, file2, file3, file4} {
142 require.NoError(t, os.MkdirAll(filepath.Dir(file), 0o755))
143 require.NoError(t, os.WriteFile(file, []byte("test"), 0o644))
146 matches, truncated, err := GlobWithDoubleStar("a/b/c/file1.txt", testDir, 0)
147 require.NoError(t, err)
148 require.False(t, truncated)
150 require.Equal(t, []string{file1}, matches)
153 t.Run("returns results sorted by modification time (newest first)", func(t *testing.T) {
154 testDir := t.TempDir()
156 file1 := filepath.Join(testDir, "file1.txt")
157 require.NoError(t, os.WriteFile(file1, []byte("first"), 0o644))
159 file2 := filepath.Join(testDir, "file2.txt")
160 require.NoError(t, os.WriteFile(file2, []byte("second"), 0o644))
162 file3 := filepath.Join(testDir, "file3.txt")
163 require.NoError(t, os.WriteFile(file3, []byte("third"), 0o644))
167 m2 := base.Add(10 * time.Hour)
168 m3 := base.Add(20 * time.Hour)
170 require.NoError(t, os.Chtimes(file1, m1, m1))
171 require.NoError(t, os.Chtimes(file2, m2, m2))
172 require.NoError(t, os.Chtimes(file3, m3, m3))
174 matches, truncated, err := GlobWithDoubleStar("*.txt", testDir, 0)
175 require.NoError(t, err)
176 require.False(t, truncated)
178 require.Equal(t, []string{file3, file2, file1}, matches)
181 t.Run("handles empty directory", func(t *testing.T) {
182 testDir := t.TempDir()
184 matches, truncated, err := GlobWithDoubleStar("**", testDir, 0)
185 require.NoError(t, err)
186 require.False(t, truncated)
187 // Even empty directories should return the directory itself
188 require.Equal(t, []string{testDir}, matches)
191 t.Run("handles non-existent search path", func(t *testing.T) {
192 nonExistentDir := filepath.Join(t.TempDir(), "does", "not", "exist")
194 matches, truncated, err := GlobWithDoubleStar("**", nonExistentDir, 0)
195 require.Error(t, err, "Should return error for non-existent search path")
196 require.False(t, truncated)
197 require.Empty(t, matches)
200 t.Run("respects basic ignore patterns", func(t *testing.T) {
201 testDir := t.TempDir()
203 rootIgnore := filepath.Join(testDir, ".crushignore")
205 require.NoError(t, os.WriteFile(rootIgnore, []byte("*.tmp\nbackup/\n"), 0o644))
207 goodFile := filepath.Join(testDir, "good.txt")
208 require.NoError(t, os.WriteFile(goodFile, []byte("content"), 0o644))
210 badFile := filepath.Join(testDir, "bad.tmp")
211 require.NoError(t, os.WriteFile(badFile, []byte("temp content"), 0o644))
213 goodDir := filepath.Join(testDir, "src")
214 require.NoError(t, os.MkdirAll(goodDir, 0o755))
216 ignoredDir := filepath.Join(testDir, "backup")
217 require.NoError(t, os.MkdirAll(ignoredDir, 0o755))
219 ignoredFileInDir := filepath.Join(testDir, "backup", "old.txt")
220 require.NoError(t, os.WriteFile(ignoredFileInDir, []byte("old content"), 0o644))
222 matches, truncated, err := GlobWithDoubleStar("*.tmp", testDir, 0)
223 require.NoError(t, err)
224 require.False(t, truncated)
225 require.Empty(t, matches, "Expected no matches for '*.tmp' pattern (should be ignored)")
227 matches, truncated, err = GlobWithDoubleStar("backup", testDir, 0)
228 require.NoError(t, err)
229 require.False(t, truncated)
230 require.Empty(t, matches, "Expected no matches for 'backup' pattern (should be ignored)")
232 matches, truncated, err = GlobWithDoubleStar("*.txt", testDir, 0)
233 require.NoError(t, err)
234 require.False(t, truncated)
235 require.Equal(t, []string{goodFile}, matches)
238 t.Run("handles mixed file and directory matching with sorting", func(t *testing.T) {
239 testDir := t.TempDir()
241 oldestFile := filepath.Join(testDir, "old.rs")
242 require.NoError(t, os.WriteFile(oldestFile, []byte("old"), 0o644))
244 middleDir := filepath.Join(testDir, "mid.rs")
245 require.NoError(t, os.MkdirAll(middleDir, 0o755))
247 newestFile := filepath.Join(testDir, "new.rs")
248 require.NoError(t, os.WriteFile(newestFile, []byte("new"), 0o644))
252 tMiddle := base.Add(10 * time.Hour)
253 tNewest := base.Add(20 * time.Hour)
255 // Reverse the expected order
256 require.NoError(t, os.Chtimes(newestFile, tOldest, tOldest))
257 require.NoError(t, os.Chtimes(middleDir, tMiddle, tMiddle))
258 require.NoError(t, os.Chtimes(oldestFile, tNewest, tNewest))
260 matches, truncated, err := GlobWithDoubleStar("*.rs", testDir, 0)
261 require.NoError(t, err)
262 require.False(t, truncated)
263 require.Len(t, matches, 3)
265 // Results should be sorted by mod time, but we set the oldestFile
266 // to have the most recent mod time
267 require.Equal(t, []string{oldestFile, middleDir, newestFile}, matches)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list