]> git.ipfire.org Git - thirdparty/git.git/blob - t/t7814-grep-recurse-submodules.sh
Sync with 2.33.5
[thirdparty/git.git] / t / t7814-grep-recurse-submodules.sh
1 #!/bin/sh
2
3 test_description='Test grep recurse-submodules feature
4
5 This test verifies the recurse-submodules feature correctly greps across
6 submodules.
7 '
8
9 . ./test-lib.sh
10
11 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
12 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
13
14 test_expect_success 'setup directory structure and submodule' '
15 echo "(1|2)d(3|4)" >a &&
16 mkdir b &&
17 echo "(3|4)" >b/b &&
18 git add a b &&
19 git commit -m "add a and b" &&
20 test_tick &&
21 git init submodule &&
22 echo "(1|2)d(3|4)" >submodule/a &&
23 git -C submodule add a &&
24 git -C submodule commit -m "add a" &&
25 git submodule add ./submodule &&
26 git commit -m "added submodule" &&
27 test_tick
28 '
29
30 test_expect_success 'grep correctly finds patterns in a submodule' '
31 cat >expect <<-\EOF &&
32 a:(1|2)d(3|4)
33 b/b:(3|4)
34 submodule/a:(1|2)d(3|4)
35 EOF
36
37 git grep -e "(3|4)" --recurse-submodules >actual &&
38 test_cmp expect actual
39 '
40
41 test_expect_success 'grep finds patterns in a submodule via config' '
42 test_config submodule.recurse true &&
43 # expect from previous test
44 git grep -e "(3|4)" >actual &&
45 test_cmp expect actual
46 '
47
48 test_expect_success 'grep --no-recurse-submodules overrides config' '
49 test_config submodule.recurse true &&
50 cat >expect <<-\EOF &&
51 a:(1|2)d(3|4)
52 b/b:(3|4)
53 EOF
54
55 git grep -e "(3|4)" --no-recurse-submodules >actual &&
56 test_cmp expect actual
57 '
58
59 test_expect_success 'grep and basic pathspecs' '
60 cat >expect <<-\EOF &&
61 submodule/a:(1|2)d(3|4)
62 EOF
63
64 git grep -e. --recurse-submodules -- submodule >actual &&
65 test_cmp expect actual
66 '
67
68 test_expect_success 'grep and nested submodules' '
69 git init submodule/sub &&
70 echo "(1|2)d(3|4)" >submodule/sub/a &&
71 git -C submodule/sub add a &&
72 git -C submodule/sub commit -m "add a" &&
73 test_tick &&
74 git -C submodule submodule add ./sub &&
75 git -C submodule add sub &&
76 git -C submodule commit -m "added sub" &&
77 test_tick &&
78 git add submodule &&
79 git commit -m "updated submodule" &&
80 test_tick &&
81
82 cat >expect <<-\EOF &&
83 a:(1|2)d(3|4)
84 b/b:(3|4)
85 submodule/a:(1|2)d(3|4)
86 submodule/sub/a:(1|2)d(3|4)
87 EOF
88
89 git grep -e "(3|4)" --recurse-submodules >actual &&
90 test_cmp expect actual
91 '
92
93 test_expect_success 'grep and multiple patterns' '
94 cat >expect <<-\EOF &&
95 a:(1|2)d(3|4)
96 submodule/a:(1|2)d(3|4)
97 submodule/sub/a:(1|2)d(3|4)
98 EOF
99
100 git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual &&
101 test_cmp expect actual
102 '
103
104 test_expect_success 'grep and multiple patterns' '
105 cat >expect <<-\EOF &&
106 b/b:(3|4)
107 EOF
108
109 git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual &&
110 test_cmp expect actual
111 '
112
113 test_expect_success 'basic grep tree' '
114 cat >expect <<-\EOF &&
115 HEAD:a:(1|2)d(3|4)
116 HEAD:b/b:(3|4)
117 HEAD:submodule/a:(1|2)d(3|4)
118 HEAD:submodule/sub/a:(1|2)d(3|4)
119 EOF
120
121 git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
122 test_cmp expect actual
123 '
124
125 test_expect_success 'grep tree HEAD^' '
126 cat >expect <<-\EOF &&
127 HEAD^:a:(1|2)d(3|4)
128 HEAD^:b/b:(3|4)
129 HEAD^:submodule/a:(1|2)d(3|4)
130 EOF
131
132 git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
133 test_cmp expect actual
134 '
135
136 test_expect_success 'grep tree HEAD^^' '
137 cat >expect <<-\EOF &&
138 HEAD^^:a:(1|2)d(3|4)
139 HEAD^^:b/b:(3|4)
140 EOF
141
142 git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
143 test_cmp expect actual
144 '
145
146 test_expect_success 'grep tree and pathspecs' '
147 cat >expect <<-\EOF &&
148 HEAD:submodule/a:(1|2)d(3|4)
149 HEAD:submodule/sub/a:(1|2)d(3|4)
150 EOF
151
152 git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual &&
153 test_cmp expect actual
154 '
155
156 test_expect_success 'grep tree and pathspecs' '
157 cat >expect <<-\EOF &&
158 HEAD:submodule/a:(1|2)d(3|4)
159 HEAD:submodule/sub/a:(1|2)d(3|4)
160 EOF
161
162 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual &&
163 test_cmp expect actual
164 '
165
166 test_expect_success 'grep tree and more pathspecs' '
167 cat >expect <<-\EOF &&
168 HEAD:submodule/a:(1|2)d(3|4)
169 EOF
170
171 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual &&
172 test_cmp expect actual
173 '
174
175 test_expect_success 'grep tree and more pathspecs' '
176 cat >expect <<-\EOF &&
177 HEAD:submodule/sub/a:(1|2)d(3|4)
178 EOF
179
180 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
181 test_cmp expect actual
182 '
183
184 test_expect_success !MINGW 'grep recurse submodule colon in name' '
185 git init parent &&
186 test_when_finished "rm -rf parent" &&
187 echo "(1|2)d(3|4)" >"parent/fi:le" &&
188 git -C parent add "fi:le" &&
189 git -C parent commit -m "add fi:le" &&
190 test_tick &&
191
192 git init "su:b" &&
193 test_when_finished "rm -rf su:b" &&
194 echo "(1|2)d(3|4)" >"su:b/fi:le" &&
195 git -C "su:b" add "fi:le" &&
196 git -C "su:b" commit -m "add fi:le" &&
197 test_tick &&
198
199 test_config_global protocol.file.allow always &&
200 git -C parent submodule add "../su:b" "su:b" &&
201 git -C parent commit -m "add submodule" &&
202 test_tick &&
203
204 cat >expect <<-\EOF &&
205 fi:le:(1|2)d(3|4)
206 su:b/fi:le:(1|2)d(3|4)
207 EOF
208 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
209 test_cmp expect actual &&
210
211 cat >expect <<-\EOF &&
212 HEAD:fi:le:(1|2)d(3|4)
213 HEAD:su:b/fi:le:(1|2)d(3|4)
214 EOF
215 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual &&
216 test_cmp expect actual
217 '
218
219 test_expect_success 'grep history with moved submoules' '
220 git init parent &&
221 test_when_finished "rm -rf parent" &&
222 echo "(1|2)d(3|4)" >parent/file &&
223 git -C parent add file &&
224 git -C parent commit -m "add file" &&
225 test_tick &&
226
227 git init sub &&
228 test_when_finished "rm -rf sub" &&
229 echo "(1|2)d(3|4)" >sub/file &&
230 git -C sub add file &&
231 git -C sub commit -m "add file" &&
232 test_tick &&
233
234 test_config_global protocol.file.allow always &&
235 git -C parent submodule add ../sub dir/sub &&
236 git -C parent commit -m "add submodule" &&
237 test_tick &&
238
239 cat >expect <<-\EOF &&
240 dir/sub/file:(1|2)d(3|4)
241 file:(1|2)d(3|4)
242 EOF
243 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
244 test_cmp expect actual &&
245
246 git -C parent mv dir/sub sub-moved &&
247 git -C parent commit -m "moved submodule" &&
248 test_tick &&
249
250 cat >expect <<-\EOF &&
251 file:(1|2)d(3|4)
252 sub-moved/file:(1|2)d(3|4)
253 EOF
254 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
255 test_cmp expect actual &&
256
257 cat >expect <<-\EOF &&
258 HEAD^:dir/sub/file:(1|2)d(3|4)
259 HEAD^:file:(1|2)d(3|4)
260 EOF
261 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
262 test_cmp expect actual
263 '
264
265 test_expect_success 'grep using relative path' '
266 test_when_finished "rm -rf parent sub" &&
267 git init sub &&
268 echo "(1|2)d(3|4)" >sub/file &&
269 git -C sub add file &&
270 git -C sub commit -m "add file" &&
271 test_tick &&
272
273 git init parent &&
274 echo "(1|2)d(3|4)" >parent/file &&
275 git -C parent add file &&
276 mkdir parent/src &&
277 echo "(1|2)d(3|4)" >parent/src/file2 &&
278 git -C parent add src/file2 &&
279 test_config_global protocol.file.allow always &&
280 git -C parent submodule add ../sub &&
281 git -C parent commit -m "add files and submodule" &&
282 test_tick &&
283
284 # From top works
285 cat >expect <<-\EOF &&
286 file:(1|2)d(3|4)
287 src/file2:(1|2)d(3|4)
288 sub/file:(1|2)d(3|4)
289 EOF
290 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
291 test_cmp expect actual &&
292
293 # Relative path to top
294 cat >expect <<-\EOF &&
295 ../file:(1|2)d(3|4)
296 file2:(1|2)d(3|4)
297 ../sub/file:(1|2)d(3|4)
298 EOF
299 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
300 test_cmp expect actual &&
301
302 # Relative path to submodule
303 cat >expect <<-\EOF &&
304 ../sub/file:(1|2)d(3|4)
305 EOF
306 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
307 test_cmp expect actual
308 '
309
310 test_expect_success 'grep from a subdir' '
311 test_when_finished "rm -rf parent sub" &&
312 git init sub &&
313 echo "(1|2)d(3|4)" >sub/file &&
314 git -C sub add file &&
315 git -C sub commit -m "add file" &&
316 test_tick &&
317
318 git init parent &&
319 mkdir parent/src &&
320 echo "(1|2)d(3|4)" >parent/src/file &&
321 git -C parent add src/file &&
322 test_config_global protocol.file.allow always &&
323 git -C parent submodule add ../sub src/sub &&
324 git -C parent submodule add ../sub sub &&
325 git -C parent commit -m "add files and submodules" &&
326 test_tick &&
327
328 # Verify grep from root works
329 cat >expect <<-\EOF &&
330 src/file:(1|2)d(3|4)
331 src/sub/file:(1|2)d(3|4)
332 sub/file:(1|2)d(3|4)
333 EOF
334 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
335 test_cmp expect actual &&
336
337 # Verify grep from a subdir works
338 cat >expect <<-\EOF &&
339 file:(1|2)d(3|4)
340 sub/file:(1|2)d(3|4)
341 EOF
342 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
343 test_cmp expect actual
344 '
345
346 test_incompatible_with_recurse_submodules ()
347 {
348 test_expect_success "--recurse-submodules and $1 are incompatible" "
349 test_must_fail git grep -e. --recurse-submodules $1 2>actual &&
350 test_i18ngrep 'not supported with --recurse-submodules' actual
351 "
352 }
353
354 test_incompatible_with_recurse_submodules --untracked
355
356 test_expect_success 'grep --recurse-submodules --no-index ignores --recurse-submodules' '
357 git grep --recurse-submodules --no-index -e "^(.|.)[\d]" >actual &&
358 cat >expect <<-\EOF &&
359 a:(1|2)d(3|4)
360 submodule/a:(1|2)d(3|4)
361 submodule/sub/a:(1|2)d(3|4)
362 EOF
363 test_cmp expect actual
364 '
365
366 test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
367 # Fixed
368 test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" &&
369 test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" &&
370
371 # Basic
372 git grep -G --recurse-submodules -e "(.|.)[\d]" >actual &&
373 cat >expect <<-\EOF &&
374 a:(1|2)d(3|4)
375 submodule/a:(1|2)d(3|4)
376 submodule/sub/a:(1|2)d(3|4)
377 EOF
378 test_cmp expect actual &&
379 git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
380 test_cmp expect actual &&
381
382 # Extended
383 git grep -E --recurse-submodules -e "(.|.)[\d]" >actual &&
384 cat >expect <<-\EOF &&
385 .gitmodules:[submodule "submodule"]
386 .gitmodules: path = submodule
387 .gitmodules: url = ./submodule
388 a:(1|2)d(3|4)
389 submodule/.gitmodules:[submodule "sub"]
390 submodule/a:(1|2)d(3|4)
391 submodule/sub/a:(1|2)d(3|4)
392 EOF
393 test_cmp expect actual &&
394 git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual &&
395 test_cmp expect actual &&
396 git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual &&
397 test_cmp expect actual &&
398
399 # Perl
400 if test_have_prereq PCRE
401 then
402 git grep -P --recurse-submodules -e "(.|.)[\d]" >actual &&
403 cat >expect <<-\EOF &&
404 a:(1|2)d(3|4)
405 b/b:(3|4)
406 submodule/a:(1|2)d(3|4)
407 submodule/sub/a:(1|2)d(3|4)
408 EOF
409 test_cmp expect actual &&
410 git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
411 test_cmp expect actual
412 fi
413 '
414
415 test_expect_success 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '
416 test_when_finished "git -C submodule checkout .gitmodules" &&
417 rm submodule/.gitmodules &&
418 git grep --recurse-submodules -e "(.|.)[\d]" >actual &&
419 cat >expect <<-\EOF &&
420 a:(1|2)d(3|4)
421 submodule/a:(1|2)d(3|4)
422 submodule/sub/a:(1|2)d(3|4)
423 EOF
424 test_cmp expect actual
425 '
426
427 reset_and_clean () {
428 git reset --hard &&
429 git clean -fd &&
430 git submodule foreach --recursive 'git reset --hard' &&
431 git submodule foreach --recursive 'git clean -fd'
432 }
433
434 test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
435 reset_and_clean &&
436 echo "A modified line in submodule" >>submodule/a &&
437 echo "submodule/a:A modified line in submodule" >expect &&
438 git grep --recurse-submodules "A modified line in submodule" >actual &&
439 test_cmp expect actual
440 '
441
442 test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
443 reset_and_clean &&
444 echo "A modified line in submodule" >>submodule/a &&
445 test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
446 test_must_be_empty actual
447 '
448
449 test_expect_failure 'grep --textconv: superproject .gitattributes does not affect submodules' '
450 reset_and_clean &&
451 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
452 echo "a diff=d2x" >.gitattributes &&
453
454 cat >expect <<-\EOF &&
455 a:(1|2)x(3|4)
456 EOF
457 git grep --textconv --recurse-submodules x >actual &&
458 test_cmp expect actual
459 '
460
461 test_expect_failure 'grep --textconv: superproject .gitattributes (from index) does not affect submodules' '
462 reset_and_clean &&
463 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
464 echo "a diff=d2x" >.gitattributes &&
465 git add .gitattributes &&
466 rm .gitattributes &&
467
468 cat >expect <<-\EOF &&
469 a:(1|2)x(3|4)
470 EOF
471 git grep --textconv --recurse-submodules x >actual &&
472 test_cmp expect actual
473 '
474
475 test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' '
476 reset_and_clean &&
477 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
478 super_attr="$(git rev-parse --git-path info/attributes)" &&
479 test_when_finished "rm -f \"$super_attr\"" &&
480 echo "a diff=d2x" >"$super_attr" &&
481
482 cat >expect <<-\EOF &&
483 a:(1|2)x(3|4)
484 EOF
485 git grep --textconv --recurse-submodules x >actual &&
486 test_cmp expect actual
487 '
488
489 # Note: what currently prevents this test from passing is not that the
490 # .gitattributes file from "./submodule" is being ignored, but that it is being
491 # propagated to the nested "./submodule/sub" files.
492 #
493 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes' '
494 reset_and_clean &&
495 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
496 echo "a diff=d2x" >submodule/.gitattributes &&
497
498 cat >expect <<-\EOF &&
499 submodule/a:(1|2)x(3|4)
500 EOF
501 git grep --textconv --recurse-submodules x >actual &&
502 test_cmp expect actual
503 '
504
505 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes (from index)' '
506 reset_and_clean &&
507 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
508 echo "a diff=d2x" >submodule/.gitattributes &&
509 git -C submodule add .gitattributes &&
510 rm submodule/.gitattributes &&
511
512 cat >expect <<-\EOF &&
513 submodule/a:(1|2)x(3|4)
514 EOF
515 git grep --textconv --recurse-submodules x >actual &&
516 test_cmp expect actual
517 '
518
519 test_expect_failure 'grep --textconv correctly reads submodule .git/info/attributes' '
520 reset_and_clean &&
521 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
522
523 submodule_attr="$(git -C submodule rev-parse --path-format=absolute --git-path info/attributes)" &&
524 test_when_finished "rm -f \"$submodule_attr\"" &&
525 echo "a diff=d2x" >"$submodule_attr" &&
526
527 cat >expect <<-\EOF &&
528 submodule/a:(1|2)x(3|4)
529 EOF
530 git grep --textconv --recurse-submodules x >actual &&
531 test_cmp expect actual
532 '
533
534 test_expect_failure 'grep saves textconv cache in the appropriate repository' '
535 reset_and_clean &&
536 test_config_global diff.d2x_cached.textconv "sed -e \"s/d/x/\"" &&
537 test_config_global diff.d2x_cached.cachetextconv true &&
538 echo "a diff=d2x_cached" >submodule/.gitattributes &&
539
540 # We only read/write to the textconv cache when grepping from an OID,
541 # as the working tree file might have modifications.
542 git grep --textconv --cached --recurse-submodules x &&
543
544 super_textconv_cache="$(git rev-parse --git-path refs/notes/textconv/d2x_cached)" &&
545 sub_textconv_cache="$(git -C submodule rev-parse \
546 --path-format=absolute --git-path refs/notes/textconv/d2x_cached)" &&
547 test_path_is_missing "$super_textconv_cache" &&
548 test_path_is_file "$sub_textconv_cache"
549 '
550
551 test_done