dir.c: literal match with wildcard in pathspec should still glob
When a path with wildcard characters, e.g. 'f*o', exists in the working tree, "git add -- 'f*o'" stops after happily finding that there is 'f*o' and adding it to the index, without realizing there may be other paths, e.g. 'foooo', that may match the given pathspec. This is because dir.c:do_match_pathspec() disables further matches with pathspec when it finds an exact match. Reported-by: piotrsiupa <piotrsiupa@gmail.com> Helped-by: Jeff King <peff@peff.net> Signed-off-by: K Jayatheerth <jayatheerthkulkarni2005@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
K Jayatheerth committed
May 3, 2025 at 11:37 UTC
ec727e189cce9e8457e2b00e0756cfdf325a12d9
3 files changed
+432
-1
dir.c
+2
-1
@@ -519,7 +519,8 @@ static int do_match_pathspec(struct index_state *istate,
519
( exclude && !(ps->items[i].magic & PATHSPEC_EXCLUDE)))
520
continue;
521
522
- if (seen && seen[i] == MATCHED_EXACTLY)
522
+ if (seen && seen[i] == MATCHED_EXACTLY &&
523
+ ps->items[i].nowildcard_len == ps->items[i].len)
524
continue;
525
/*
526
* Make exclude patterns optional and never report
t/meson.build
+1
@@ -787,6 +787,7 @@ integration_tests = [
787
't6134-pathspec-in-submodule.sh',
788
't6135-pathspec-with-attrs.sh',
789
't6136-pathspec-in-bare.sh',
790
+ 't6137-pathspec-wildcards-literal.sh',
791
't6200-fmt-merge-msg.sh',
792
't6300-for-each-ref.sh',
793
't6301-for-each-ref-errors.sh',
t/t6137-pathspec-wildcards-literal.sh
new
+429
@@ -0,0 +1,429 @@
1
+#!/bin/sh
2
+test_description='test wildcards and literals with git add/commit (subshell style)'
3
+
4
+. ./test-lib.sh
5
+
6
+test_have_prereq FUNNYNAMES || {
7
+ skip_all='skipping: needs FUNNYNAMES (non-Windows only)'
8
+ test_done
9
+}
10
+
11
+prepare_test_files () {
12
+ for f in "*" "**" "?" "[abc]" "a" "f*" "f**" "f?z" "foo*bar" "hello?world" "hello_world"
13
+ do
14
+ >"$f" || return
15
+ done
16
+}
17
+
18
+test_expect_success 'add wildcard *' '
19
+ git init test-asterisk &&
20
+ (
21
+ cd test-asterisk &&
22
+ prepare_test_files &&
23
+ git add "*" &&
24
+ cat >expect <<-EOF &&
25
+ *
26
+ **
27
+ ?
28
+ [abc]
29
+ a
30
+ f*
31
+ f**
32
+ f?z
33
+ foo*bar
34
+ hello?world
35
+ hello_world
36
+ EOF
37
+ git ls-files >actual &&
38
+ test_cmp expect actual
39
+ )
40
+'
41
+
42
+test_expect_success 'add literal \*' '
43
+ git init test-asterisk-literal &&
44
+ (
45
+ cd test-asterisk-literal &&
46
+ prepare_test_files &&
47
+ git add "\*" &&
48
+ cat >expect <<-EOF &&
49
+ *
50
+ EOF
51
+ git ls-files >actual &&
52
+ test_cmp expect actual
53
+ )
54
+'
55
+
56
+test_expect_success 'add wildcard **' '
57
+ git init test-dstar &&
58
+ (
59
+ cd test-dstar &&
60
+ prepare_test_files &&
61
+ git add "**" &&
62
+ cat >expect <<-EOF &&
63
+ *
64
+ **
65
+ ?
66
+ [abc]
67
+ a
68
+ f*
69
+ f**
70
+ f?z
71
+ foo*bar
72
+ hello?world
73
+ hello_world
74
+ EOF
75
+ git ls-files >actual &&
76
+ test_cmp expect actual
77
+ )
78
+'
79
+
80
+test_expect_success 'add wildcard ?' '
81
+ git init test-qmark &&
82
+ (
83
+ cd test-qmark &&
84
+ prepare_test_files &&
85
+ git add "?" &&
86
+ cat >expect <<-\EOF | sort &&
87
+ *
88
+ ?
89
+ a
90
+ EOF
91
+ git ls-files | sort >actual &&
92
+ test_cmp expect actual
93
+ )
94
+'
95
+
96
+test_expect_success 'add wildcard [abc]' '
97
+ git init test-brackets &&
98
+ (
99
+ cd test-brackets &&
100
+ prepare_test_files &&
101
+ git add "[abc]" &&
102
+ cat >expect <<-\EOF | sort &&
103
+ [abc]
104
+ a
105
+ EOF
106
+ git ls-files | sort >actual &&
107
+ test_cmp expect actual
108
+ )
109
+'
110
+
111
+test_expect_success 'add wildcard f*' '
112
+ git init test-f-wild &&
113
+ (
114
+ cd test-f-wild &&
115
+ prepare_test_files &&
116
+ git add "f*" &&
117
+ cat >expect <<-\EOF | sort &&
118
+ f*
119
+ f**
120
+ f?z
121
+ foo*bar
122
+ EOF
123
+ git ls-files | sort >actual &&
124
+ test_cmp expect actual
125
+ )
126
+'
127
+
128
+test_expect_success 'add literal f\*' '
129
+ git init test-f-lit &&
130
+ (
131
+ cd test-f-lit &&
132
+ prepare_test_files &&
133
+ git add "f\*" &&
134
+ cat >expect <<-\EOF &&
135
+ f*
136
+ EOF
137
+ git ls-files >actual &&
138
+ test_cmp expect actual
139
+ )
140
+'
141
+
142
+test_expect_success 'add wildcard f**' '
143
+ git init test-fdstar &&
144
+ (
145
+ cd test-fdstar &&
146
+ prepare_test_files &&
147
+ git add "f**" &&
148
+ cat >expect <<-\EOF | sort &&
149
+ f*
150
+ f**
151
+ f?z
152
+ foo*bar
153
+ EOF
154
+ git ls-files | sort >actual &&
155
+ test_cmp expect actual
156
+ )
157
+'
158
+
159
+test_expect_success 'add literal f\*\*' '
160
+ git init test-fdstar-lit &&
161
+ (
162
+ cd test-fdstar-lit &&
163
+ prepare_test_files &&
164
+ git add "f\*\*" &&
165
+ cat >expect <<-\EOF &&
166
+ f**
167
+ EOF
168
+ git ls-files >actual &&
169
+ test_cmp expect actual
170
+ )
171
+'
172
+
173
+test_expect_success 'add wildcard f?z' '
174
+ git init test-fqz &&
175
+ (
176
+ cd test-fqz &&
177
+ prepare_test_files &&
178
+ git add "f?z" &&
179
+ cat >expect <<-\EOF &&
180
+ f?z
181
+ EOF
182
+ git ls-files >actual &&
183
+ test_cmp expect actual
184
+ )
185
+'
186
+
187
+test_expect_success 'add literal \? literal' '
188
+ git init test-q-lit &&
189
+ (
190
+ cd test-q-lit &&
191
+ prepare_test_files &&
192
+ git add "\?" &&
193
+ cat >expect <<-\EOF &&
194
+ ?
195
+ EOF
196
+ git ls-files >actual &&
197
+ test_cmp expect actual
198
+ )
199
+'
200
+
201
+test_expect_success 'add wildcard foo*bar' '
202
+ git init test-foobar &&
203
+ (
204
+ cd test-foobar &&
205
+ prepare_test_files &&
206
+ git add "foo*bar" &&
207
+ cat >expect <<-\EOF &&
208
+ foo*bar
209
+ EOF
210
+ git ls-files >actual &&
211
+ test_cmp expect actual
212
+ )
213
+'
214
+
215
+test_expect_success 'add wildcard hello?world' '
216
+ git init test-hellowild &&
217
+ (
218
+ cd test-hellowild &&
219
+ prepare_test_files &&
220
+ git add "hello?world" &&
221
+ cat >expect <<-\EOF &&
222
+ hello?world
223
+ hello_world
224
+ EOF
225
+ git ls-files >actual &&
226
+ test_cmp expect actual
227
+ )
228
+'
229
+
230
+test_expect_success 'add literal hello\?world' '
231
+ git init test-hellolit &&
232
+ (
233
+ cd test-hellolit &&
234
+ prepare_test_files &&
235
+ git add "hello\?world" &&
236
+ cat >expect <<-\EOF &&
237
+ hello?world
238
+ EOF
239
+ git ls-files >actual &&
240
+ test_cmp expect actual
241
+ )
242
+'
243
+
244
+test_expect_success 'add literal [abc]' '
245
+ git init test-brackets-lit &&
246
+ (
247
+ cd test-brackets-lit &&
248
+ prepare_test_files &&
249
+ git add "\[abc\]" &&
250
+ cat >expect <<-\EOF &&
251
+ [abc]
252
+ EOF
253
+ git ls-files >actual &&
254
+ test_cmp expect actual
255
+ )
256
+'
257
+
258
+test_expect_success 'commit: wildcard *' '
259
+ git init test-c-asterisk &&
260
+ (
261
+ cd test-c-asterisk &&
262
+ prepare_test_files &&
263
+ git add . &&
264
+ git commit -m "c1" -- "*" &&
265
+ cat >expect <<-EOF &&
266
+ *
267
+ **
268
+ ?
269
+ [abc]
270
+ a
271
+ f*
272
+ f**
273
+ f?z
274
+ foo*bar
275
+ hello?world
276
+ hello_world
277
+ EOF
278
+ git ls-tree -r --name-only HEAD >actual &&
279
+ test_cmp expect actual
280
+ )
281
+'
282
+
283
+test_expect_success 'commit: literal *' '
284
+ git init test-c-asterisk-lit &&
285
+ (
286
+ cd test-c-asterisk-lit &&
287
+ prepare_test_files &&
288
+ git add . &&
289
+ git commit -m "c2" -- "\*" &&
290
+ cat >expect <<-EOF &&
291
+ *
292
+ EOF
293
+ git ls-tree -r --name-only HEAD >actual &&
294
+ test_cmp expect actual
295
+ )
296
+'
297
+
298
+test_expect_success 'commit: wildcard f*' '
299
+ git init test-c-fwild &&
300
+ (
301
+ cd test-c-fwild &&
302
+ prepare_test_files &&
303
+ git add . &&
304
+ git commit -m "c3" -- "f*" &&
305
+ cat >expect <<-EOF &&
306
+ f*
307
+ f**
308
+ f?z
309
+ foo*bar
310
+ EOF
311
+ git ls-tree -r --name-only HEAD >actual &&
312
+ test_cmp expect actual
313
+ )
314
+'
315
+
316
+test_expect_success 'commit: literal f\*' '
317
+ git init test-c-flit &&
318
+ (
319
+ cd test-c-flit &&
320
+ prepare_test_files &&
321
+ git add . &&
322
+ git commit -m "c4" -- "f\*" &&
323
+ cat >expect <<-EOF &&
324
+ f*
325
+ EOF
326
+ git ls-tree -r --name-only HEAD >actual &&
327
+ test_cmp expect actual
328
+ )
329
+'
330
+
331
+test_expect_success 'commit: wildcard pathspec limits commit' '
332
+ git init test-c-pathlimit &&
333
+ (
334
+ cd test-c-pathlimit &&
335
+ prepare_test_files &&
336
+ git add . &&
337
+ git commit -m "c5" -- "f**" &&
338
+ cat >expect <<-EOF &&
339
+ f*
340
+ f**
341
+ f?z
342
+ foo*bar
343
+ EOF
344
+ git ls-tree -r --name-only HEAD >actual &&
345
+ test_cmp expect actual
346
+ )
347
+'
348
+
349
+test_expect_success 'commit: literal f\*\*' '
350
+ git init test-c-fdstar-lit &&
351
+ (
352
+ cd test-c-fdstar-lit &&
353
+ prepare_test_files &&
354
+ git add . &&
355
+ git commit -m "c6" -- "f\*\*" &&
356
+ cat >expect <<-EOF &&
357
+ f**
358
+ EOF
359
+ git ls-tree -r --name-only HEAD >actual &&
360
+ test_cmp expect actual
361
+ )
362
+'
363
+
364
+test_expect_success 'commit: wildcard ?' '
365
+ git init test-c-qwild &&
366
+ (
367
+ cd test-c-qwild &&
368
+ prepare_test_files &&
369
+ git add . &&
370
+ git commit -m "c7" -- "?" &&
371
+ cat >expect <<-EOF &&
372
+ *
373
+ ?
374
+ a
375
+ EOF
376
+ git ls-tree -r --name-only HEAD | sort >actual &&
377
+ sort expect >expect.sorted &&
378
+ test_cmp expect.sorted actual
379
+ )
380
+'
381
+
382
+test_expect_success 'commit: literal \?' '
383
+ git init test-c-qlit &&
384
+ (
385
+ cd test-c-qlit &&
386
+ prepare_test_files &&
387
+ git add . &&
388
+ git commit -m "c8" -- "\?" &&
389
+ cat >expect <<-EOF &&
390
+ ?
391
+ EOF
392
+ git ls-tree -r --name-only HEAD >actual &&
393
+ test_cmp expect actual
394
+ )
395
+'
396
+
397
+test_expect_success 'commit: wildcard hello?world' '
398
+ git init test-c-hellowild &&
399
+ (
400
+ cd test-c-hellowild &&
401
+ prepare_test_files &&
402
+ git add . &&
403
+ git commit -m "c9" -- "hello?world" &&
404
+ cat >expect <<-EOF &&
405
+ hello?world
406
+ hello_world
407
+ EOF
408
+ git ls-tree -r --name-only HEAD | sort >actual &&
409
+ sort expect >expect.sorted &&
410
+ test_cmp expect.sorted actual
411
+ )
412
+'
413
+
414
+test_expect_success 'commit: literal hello\?world' '
415
+ git init test-c-hellolit &&
416
+ (
417
+ cd test-c-hellolit &&
418
+ prepare_test_files &&
419
+ git add . &&
420
+ git commit -m "c10" -- "hello\?world" &&
421
+ cat >expect <<-EOF &&
422
+ hello?world
423
+ EOF
424
+ git ls-tree -r --name-only HEAD >actual &&
425
+ test_cmp expect actual
426
+ )
427
+'
428
+
429
+test_done