on main help sign in
fix(fsext): prevent `.*` on gitignore from ignoring entire root dir (#766)
0354fefJames Trew
internal/fsext/ls.go+9−3
@@ -125,18 +125,24 @@ func (dl *directoryLister) shouldIgnore(path string, ignorePatterns []string) bo
125 }
125 }
126 }
126 }
127
127
128+ // Don't apply gitignore rules to the root directory itself
129+ // In gitignore semantics, patterns don't apply to the repo root
130+ if path == dl.rootPath {
131+ return false
132+ }
133+
128 relPath, err := filepath.Rel(dl.rootPath, path)
134 relPath, err := filepath.Rel(dl.rootPath, path)
129 if err != nil {
135 if err != nil {
130 relPath = path
136 relPath = path
131 }
137 }
132
138
133 if commonIgnorePatterns().MatchesPath(relPath) {
139 if commonIgnorePatterns().MatchesPath(relPath) {
134− slog.Debug("ingoring common pattern", "path", relPath)
140+ slog.Debug("ignoring common pattern", "path", relPath)
135 return true
141 return true
136 }
142 }
137
143
138 if dl.getIgnore(filepath.Dir(path)).MatchesPath(relPath) {
144 if dl.getIgnore(filepath.Dir(path)).MatchesPath(relPath) {
139− slog.Debug("ingoring dir pattern", "path", relPath, "dir", filepath.Dir(path))
145+ slog.Debug("ignoring dir pattern", "path", relPath, "dir", filepath.Dir(path))
140 return true
146 return true
141 }
147 }
142
148
@@ -145,7 +151,7 @@ func (dl *directoryLister) shouldIgnore(path string, ignorePatterns []string) bo
145 }
151 }
146
152
147 if homeIgnore().MatchesPath(relPath) {
153 if homeIgnore().MatchesPath(relPath) {
148− slog.Debug("ingoring home dir pattern", "path", relPath)
154+ slog.Debug("ignoring home dir pattern", "path", relPath)
149 return true
155 return true
150 }
156 }
151
157
internal/fsext/ls_test.gonew file+66
@@ -0,0 +1,66 @@
1+package fsext
2+
3+import (
4+ "os"
5+ "path/filepath"
6+ "testing"
7+
8+ "github.com/stretchr/testify/assert"
9+ "github.com/stretchr/testify/require"
10+)
11+
12+func chdir(t *testing.T, dir string) {
13+ original, err := os.Getwd()
14+ require.NoError(t, err)
15+
16+ err = os.Chdir(dir)
17+ require.NoError(t, err)
18+
19+ t.Cleanup(func() {
20+ err := os.Chdir(original)
21+ require.NoError(t, err)
22+ })
23+}
24+
25+func TestListDirectory(t *testing.T) {
26+ tempDir := t.TempDir()
27+ chdir(t, tempDir)
28+
29+ testFiles := map[string]string{
30+ "regular.txt": "content",
31+ ".hidden": "hidden content",
32+ ".gitignore": ".*\n*.log\n",
33+ "subdir/file.go": "package main",
34+ "subdir/.another": "more hidden",
35+ "build.log": "build output",
36+ }
37+
38+ for filePath, content := range testFiles {
39+ dir := filepath.Dir(filePath)
40+ if dir != "." {
41+ require.NoError(t, os.MkdirAll(dir, 0o755))
42+ }
43+
44+ err := os.WriteFile(filePath, []byte(content), 0o644)
45+ require.NoError(t, err)
46+ }
47+
48+ files, truncated, err := ListDirectory(".", nil, 0)
49+ require.NoError(t, err)
50+ assert.False(t, truncated)
51+ assert.Equal(t, len(files), 4)
52+
53+ fileSet := make(map[string]bool)
54+ for _, file := range files {
55+ fileSet[filepath.ToSlash(file)] = true
56+ }
57+
58+ assert.True(t, fileSet["./regular.txt"])
59+ assert.True(t, fileSet["./subdir/"])
60+ assert.True(t, fileSet["./subdir/file.go"])
61+ assert.True(t, fileSet["./regular.txt"])
62+
63+ assert.False(t, fileSet["./.hidden"])
64+ assert.False(t, fileSet["./.gitignore"])
65+ assert.False(t, fileSet["./build.log"])
66+}