1+ package dev.nx.gradle.utils
2+
3+ import java.io.File
4+ import org.junit.jupiter.api.Assertions.*
5+ import org.junit.jupiter.api.Test
6+ import org.junit.jupiter.api.io.TempDir
7+
8+ class GitIgnoreClassifierTest {
9+
10+ @Test
11+ fun `test isIgnored with no gitignore file` (@TempDir tempDir : File ) {
12+ val classifier = GitIgnoreClassifier (tempDir)
13+
14+ val file = File (tempDir, " src/main.kt" )
15+ assertFalse(classifier.isIgnored(file))
16+ }
17+
18+ @Test
19+ fun `test isIgnored with simple patterns` (@TempDir tempDir : File ) {
20+ // Create .gitignore file
21+ val gitignore = File (tempDir, " .gitignore" )
22+ gitignore.writeText(
23+ """
24+ # Comments should be ignored
25+ node_modules
26+ *.log
27+ dist
28+ build
29+ """
30+ .trimIndent())
31+
32+ val classifier = GitIgnoreClassifier (tempDir)
33+
34+ // Test exact directory matches
35+ assertTrue(classifier.isIgnored(File (tempDir, " node_modules" )))
36+ assertTrue(classifier.isIgnored(File (tempDir, " node_modules/package.json" )))
37+ assertTrue(classifier.isIgnored(File (tempDir, " dist" )))
38+ assertTrue(classifier.isIgnored(File (tempDir, " dist/app.js" )))
39+ assertTrue(classifier.isIgnored(File (tempDir, " build" )))
40+ assertTrue(classifier.isIgnored(File (tempDir, " build/classes/Main.class" )))
41+
42+ // Test wildcard patterns
43+ assertTrue(classifier.isIgnored(File (tempDir, " app.log" )))
44+ assertTrue(classifier.isIgnored(File (tempDir, " logs/error.log" )))
45+
46+ // Test files that should NOT be ignored
47+ assertFalse(classifier.isIgnored(File (tempDir, " src/main.kt" )))
48+ assertFalse(classifier.isIgnored(File (tempDir, " README.md" )))
49+ assertFalse(classifier.isIgnored(File (tempDir, " package.json" )))
50+ }
51+
52+ @Test
53+ fun `test isIgnored with nested paths` (@TempDir tempDir : File ) {
54+ val gitignore = File (tempDir, " .gitignore" )
55+ gitignore.writeText(
56+ """
57+ build
58+ .gradle
59+ out
60+ """
61+ .trimIndent())
62+
63+ val classifier = GitIgnoreClassifier (tempDir)
64+
65+ // Test nested build directories
66+ assertTrue(classifier.isIgnored(File (tempDir, " build" )))
67+ assertTrue(classifier.isIgnored(File (tempDir, " build/libs" )))
68+ assertTrue(classifier.isIgnored(File (tempDir, " build/libs/app.jar" )))
69+ assertTrue(classifier.isIgnored(File (tempDir, " project/build" )))
70+ assertTrue(classifier.isIgnored(File (tempDir, " project/build/classes/Main.class" )))
71+
72+ // Test .gradle directories
73+ assertTrue(classifier.isIgnored(File (tempDir, " .gradle" )))
74+ assertTrue(classifier.isIgnored(File (tempDir, " .gradle/caches" )))
75+
76+ // Test out directories
77+ assertTrue(classifier.isIgnored(File (tempDir, " out" )))
78+ assertTrue(classifier.isIgnored(File (tempDir, " out/production" )))
79+ }
80+
81+ @Test
82+ fun `test isIgnored with wildcard patterns` (@TempDir tempDir : File ) {
83+ val gitignore = File (tempDir, " .gitignore" )
84+ gitignore.writeText(
85+ """
86+ *.class
87+ *.jar
88+ *.log
89+ **/*.tmp
90+ """
91+ .trimIndent())
92+
93+ val classifier = GitIgnoreClassifier (tempDir)
94+
95+ // Test file extension wildcards
96+ assertTrue(classifier.isIgnored(File (tempDir, " Main.class" )))
97+ assertTrue(classifier.isIgnored(File (tempDir, " build/classes/Main.class" )))
98+ assertTrue(classifier.isIgnored(File (tempDir, " app.jar" )))
99+ assertTrue(classifier.isIgnored(File (tempDir, " libs/dependency.jar" )))
100+ assertTrue(classifier.isIgnored(File (tempDir, " debug.log" )))
101+
102+ // Test nested tmp files
103+ assertTrue(classifier.isIgnored(File (tempDir, " temp.tmp" )))
104+ assertTrue(classifier.isIgnored(File (tempDir, " cache/temp.tmp" )))
105+
106+ // Files that should NOT match
107+ assertFalse(classifier.isIgnored(File (tempDir, " Main.kt" )))
108+ assertFalse(classifier.isIgnored(File (tempDir, " app.json" )))
109+ }
110+
111+ @Test
112+ fun `test isIgnored with directory slash patterns` (@TempDir tempDir : File ) {
113+ val gitignore = File (tempDir, " .gitignore" )
114+ gitignore.writeText(
115+ """
116+ /build/
117+ /dist/
118+ """
119+ .trimIndent())
120+
121+ val classifier = GitIgnoreClassifier (tempDir)
122+
123+ // Test root-level directories
124+ assertTrue(classifier.isIgnored(File (tempDir, " build" )))
125+ assertTrue(classifier.isIgnored(File (tempDir, " build/output.jar" )))
126+ assertTrue(classifier.isIgnored(File (tempDir, " dist" )))
127+ assertTrue(classifier.isIgnored(File (tempDir, " dist/app.js" )))
128+ }
129+
130+ @Test
131+ fun `test isIgnored with negation patterns` (@TempDir tempDir : File ) {
132+ val gitignore = File (tempDir, " .gitignore" )
133+ gitignore.writeText(
134+ """
135+ *.log
136+ !important.log
137+ """
138+ .trimIndent())
139+
140+ val classifier = GitIgnoreClassifier (tempDir)
141+
142+ // Test that .log files are ignored
143+ assertTrue(classifier.isIgnored(File (tempDir, " debug.log" )))
144+ assertTrue(classifier.isIgnored(File (tempDir, " error.log" )))
145+
146+ // Test negation pattern (important.log should NOT be ignored)
147+ assertFalse(classifier.isIgnored(File (tempDir, " important.log" )))
148+ }
149+
150+ @Test
151+ fun `test isIgnored with files outside workspace` (@TempDir tempDir : File ) {
152+ val gitignore = File (tempDir, " .gitignore" )
153+ gitignore.writeText(" build" )
154+
155+ val classifier = GitIgnoreClassifier (tempDir)
156+
157+ // File outside workspace should return false
158+ val externalFile = File (" /tmp/external/build/app.jar" )
159+ assertFalse(classifier.isIgnored(externalFile))
160+ }
161+
162+ @Test
163+ fun `test isIgnored with common build artifacts` (@TempDir tempDir : File ) {
164+ val gitignore = File (tempDir, " .gitignore" )
165+ gitignore.writeText(
166+ """
167+ # Build outputs
168+ build
169+ .gradle
170+ dist
171+ out
172+ target
173+
174+ # IDE
175+ .idea
176+ .vscode
177+
178+ # Logs
179+ *.log
180+
181+ # OS
182+ .DS_Store
183+ """
184+ .trimIndent())
185+
186+ val classifier = GitIgnoreClassifier (tempDir)
187+
188+ // Build outputs
189+ assertTrue(classifier.isIgnored(File (tempDir, " build/libs/app.jar" )))
190+ assertTrue(classifier.isIgnored(File (tempDir, " .gradle/caches" )))
191+ assertTrue(classifier.isIgnored(File (tempDir, " dist/bundle.js" )))
192+ assertTrue(classifier.isIgnored(File (tempDir, " out/production" )))
193+ assertTrue(classifier.isIgnored(File (tempDir, " target/classes" )))
194+
195+ // IDE files
196+ assertTrue(classifier.isIgnored(File (tempDir, " .idea/workspace.xml" )))
197+ assertTrue(classifier.isIgnored(File (tempDir, " .vscode/settings.json" )))
198+
199+ // Logs
200+ assertTrue(classifier.isIgnored(File (tempDir, " app.log" )))
201+ assertTrue(classifier.isIgnored(File (tempDir, " logs/error.log" )))
202+
203+ // OS files
204+ assertTrue(classifier.isIgnored(File (tempDir, " .DS_Store" )))
205+
206+ // Source files should NOT be ignored
207+ assertFalse(classifier.isIgnored(File (tempDir, " src/main/kotlin/Main.kt" )))
208+ assertFalse(classifier.isIgnored(File (tempDir, " build.gradle.kts" )))
209+ assertFalse(classifier.isIgnored(File (tempDir, " settings.gradle.kts" )))
210+ }
211+
212+ @Test
213+ fun `test isIgnored caching behavior` (@TempDir tempDir : File ) {
214+ val gitignore = File (tempDir, " .gitignore" )
215+ gitignore.writeText(" build\n *.log" )
216+
217+ // Create classifier - should load gitignore
218+ val classifier = GitIgnoreClassifier (tempDir)
219+
220+ // Test initial checks
221+ assertTrue(classifier.isIgnored(File (tempDir, " build/app.jar" )))
222+ assertTrue(classifier.isIgnored(File (tempDir, " debug.log" )))
223+
224+ // Modify gitignore file (classifier should still use cached rules)
225+ gitignore.writeText(" other" )
226+
227+ // Should still use original rules
228+ assertTrue(classifier.isIgnored(File (tempDir, " build/app.jar" )))
229+ assertTrue(classifier.isIgnored(File (tempDir, " debug.log" )))
230+
231+ // Create new classifier to pick up changes
232+ val newClassifier = GitIgnoreClassifier (tempDir)
233+ assertFalse(newClassifier.isIgnored(File (tempDir, " build/app.jar" )))
234+ assertFalse(newClassifier.isIgnored(File (tempDir, " debug.log" )))
235+ assertTrue(newClassifier.isIgnored(File (tempDir, " other" )))
236+ }
237+
238+ @Test
239+ fun `test isIgnored with empty gitignore` (@TempDir tempDir : File ) {
240+ val gitignore = File (tempDir, " .gitignore" )
241+ gitignore.writeText(" " )
242+
243+ val classifier = GitIgnoreClassifier (tempDir)
244+
245+ // Nothing should be ignored
246+ assertFalse(classifier.isIgnored(File (tempDir, " anything.txt" )))
247+ assertFalse(classifier.isIgnored(File (tempDir, " build/app.jar" )))
248+ }
249+
250+ @Test
251+ fun `test isIgnored with only comments` (@TempDir tempDir : File ) {
252+ val gitignore = File (tempDir, " .gitignore" )
253+ gitignore.writeText(
254+ """
255+ # This is a comment
256+ # Another comment
257+
258+ # Yet another comment
259+ """
260+ .trimIndent())
261+
262+ val classifier = GitIgnoreClassifier (tempDir)
263+
264+ // Nothing should be ignored
265+ assertFalse(classifier.isIgnored(File (tempDir, " anything.txt" )))
266+ assertFalse(classifier.isIgnored(File (tempDir, " build/app.jar" )))
267+ }
268+ }
0 commit comments