]> git.ipfire.org Git - thirdparty/git.git/blob - t/t7814-grep-recurse-submodules.sh
Merge branch 'jk/clone-allow-bare-and-o-together'
[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_CREATE_REPO_NO_TEMPLATE=1
10 . ./test-lib.sh
11
12 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
13 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
14
15 test_expect_success 'setup directory structure and submodule' '
16 echo "(1|2)d(3|4)" >a &&
17 mkdir b &&
18 echo "(3|4)" >b/b &&
19 git add a b &&
20 git commit -m "add a and b" &&
21 test_tick &&
22 git init submodule &&
23 echo "(1|2)d(3|4)" >submodule/a &&
24 git -C submodule add a &&
25 git -C submodule commit -m "add a" &&
26 git submodule add ./submodule &&
27 git commit -m "added submodule" &&
28 test_tick
29 '
30
31 test_expect_success 'grep correctly finds patterns in a submodule' '
32 cat >expect <<-\EOF &&
33 a:(1|2)d(3|4)
34 b/b:(3|4)
35 submodule/a:(1|2)d(3|4)
36 EOF
37
38 git grep -e "(3|4)" --recurse-submodules >actual &&
39 test_cmp expect actual
40 '
41
42 test_expect_success 'grep finds patterns in a submodule via config' '
43 test_config submodule.recurse true &&
44 # expect from previous test
45 git grep -e "(3|4)" >actual &&
46 test_cmp expect actual
47 '
48
49 test_expect_success 'grep --no-recurse-submodules overrides config' '
50 test_config submodule.recurse true &&
51 cat >expect <<-\EOF &&
52 a:(1|2)d(3|4)
53 b/b:(3|4)
54 EOF
55
56 git grep -e "(3|4)" --no-recurse-submodules >actual &&
57 test_cmp expect actual
58 '
59
60 test_expect_success 'grep and basic pathspecs' '
61 cat >expect <<-\EOF &&
62 submodule/a:(1|2)d(3|4)
63 EOF
64
65 git grep -e. --recurse-submodules -- submodule >actual &&
66 test_cmp expect actual
67 '
68
69 test_expect_success 'grep and nested submodules' '
70 git init submodule/sub &&
71 echo "(1|2)d(3|4)" >submodule/sub/a &&
72 git -C submodule/sub add a &&
73 git -C submodule/sub commit -m "add a" &&
74 test_tick &&
75 git -C submodule submodule add ./sub &&
76 git -C submodule add sub &&
77 git -C submodule commit -m "added sub" &&
78 test_tick &&
79 git add submodule &&
80 git commit -m "updated submodule" &&
81 test_tick &&
82
83 cat >expect <<-\EOF &&
84 a:(1|2)d(3|4)
85 b/b:(3|4)
86 submodule/a:(1|2)d(3|4)
87 submodule/sub/a:(1|2)d(3|4)
88 EOF
89
90 git grep -e "(3|4)" --recurse-submodules >actual &&
91 test_cmp expect actual
92 '
93
94 test_expect_success 'grep and multiple patterns' '
95 cat >expect <<-\EOF &&
96 a:(1|2)d(3|4)
97 submodule/a:(1|2)d(3|4)
98 submodule/sub/a:(1|2)d(3|4)
99 EOF
100
101 git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual &&
102 test_cmp expect actual
103 '
104
105 test_expect_success 'grep and multiple patterns' '
106 cat >expect <<-\EOF &&
107 b/b:(3|4)
108 EOF
109
110 git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual &&
111 test_cmp expect actual
112 '
113
114 test_expect_success 'basic grep tree' '
115 cat >expect <<-\EOF &&
116 HEAD:a:(1|2)d(3|4)
117 HEAD:b/b:(3|4)
118 HEAD:submodule/a:(1|2)d(3|4)
119 HEAD:submodule/sub/a:(1|2)d(3|4)
120 EOF
121
122 git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
123 test_cmp expect actual
124 '
125
126 test_expect_success 'grep tree HEAD^' '
127 cat >expect <<-\EOF &&
128 HEAD^:a:(1|2)d(3|4)
129 HEAD^:b/b:(3|4)
130 HEAD^:submodule/a:(1|2)d(3|4)
131 EOF
132
133 git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
134 test_cmp expect actual
135 '
136
137 test_expect_success 'grep tree HEAD^^' '
138 cat >expect <<-\EOF &&
139 HEAD^^:a:(1|2)d(3|4)
140 HEAD^^:b/b:(3|4)
141 EOF
142
143 git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
144 test_cmp expect actual
145 '
146
147 test_expect_success 'grep tree and pathspecs' '
148 cat >expect <<-\EOF &&
149 HEAD:submodule/a:(1|2)d(3|4)
150 HEAD:submodule/sub/a:(1|2)d(3|4)
151 EOF
152
153 git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual &&
154 test_cmp expect actual
155 '
156
157 test_expect_success 'grep tree and pathspecs' '
158 cat >expect <<-\EOF &&
159 HEAD:submodule/a:(1|2)d(3|4)
160 HEAD:submodule/sub/a:(1|2)d(3|4)
161 EOF
162
163 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual &&
164 test_cmp expect actual
165 '
166
167 test_expect_success 'grep tree and more pathspecs' '
168 cat >expect <<-\EOF &&
169 HEAD:submodule/a:(1|2)d(3|4)
170 EOF
171
172 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual &&
173 test_cmp expect actual
174 '
175
176 test_expect_success 'grep tree and more pathspecs' '
177 cat >expect <<-\EOF &&
178 HEAD:submodule/sub/a:(1|2)d(3|4)
179 EOF
180
181 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
182 test_cmp expect actual
183 '
184
185 test_expect_success !MINGW 'grep recurse submodule colon in name' '
186 git init parent &&
187 test_when_finished "rm -rf parent" &&
188 echo "(1|2)d(3|4)" >"parent/fi:le" &&
189 git -C parent add "fi:le" &&
190 git -C parent commit -m "add fi:le" &&
191 test_tick &&
192
193 git init "su:b" &&
194 test_when_finished "rm -rf su:b" &&
195 echo "(1|2)d(3|4)" >"su:b/fi:le" &&
196 git -C "su:b" add "fi:le" &&
197 git -C "su:b" commit -m "add fi:le" &&
198 test_tick &&
199
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 git -C parent submodule add ../sub dir/sub &&
235 git -C parent commit -m "add submodule" &&
236 test_tick &&
237
238 cat >expect <<-\EOF &&
239 dir/sub/file:(1|2)d(3|4)
240 file:(1|2)d(3|4)
241 EOF
242 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
243 test_cmp expect actual &&
244
245 git -C parent mv dir/sub sub-moved &&
246 git -C parent commit -m "moved submodule" &&
247 test_tick &&
248
249 cat >expect <<-\EOF &&
250 file:(1|2)d(3|4)
251 sub-moved/file:(1|2)d(3|4)
252 EOF
253 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
254 test_cmp expect actual &&
255
256 cat >expect <<-\EOF &&
257 HEAD^:dir/sub/file:(1|2)d(3|4)
258 HEAD^:file:(1|2)d(3|4)
259 EOF
260 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
261 test_cmp expect actual
262 '
263
264 test_expect_success 'grep using relative path' '
265 test_when_finished "rm -rf parent sub" &&
266 git init sub &&
267 echo "(1|2)d(3|4)" >sub/file &&
268 git -C sub add file &&
269 git -C sub commit -m "add file" &&
270 test_tick &&
271
272 git init parent &&
273 echo "(1|2)d(3|4)" >parent/file &&
274 git -C parent add file &&
275 mkdir parent/src &&
276 echo "(1|2)d(3|4)" >parent/src/file2 &&
277 git -C parent add src/file2 &&
278 git -C parent submodule add ../sub &&
279 git -C parent commit -m "add files and submodule" &&
280 test_tick &&
281
282 # From top works
283 cat >expect <<-\EOF &&
284 file:(1|2)d(3|4)
285 src/file2:(1|2)d(3|4)
286 sub/file:(1|2)d(3|4)
287 EOF
288 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
289 test_cmp expect actual &&
290
291 # Relative path to top
292 cat >expect <<-\EOF &&
293 ../file:(1|2)d(3|4)
294 file2:(1|2)d(3|4)
295 ../sub/file:(1|2)d(3|4)
296 EOF
297 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
298 test_cmp expect actual &&
299
300 # Relative path to submodule
301 cat >expect <<-\EOF &&
302 ../sub/file:(1|2)d(3|4)
303 EOF
304 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
305 test_cmp expect actual
306 '
307
308 test_expect_success 'grep from a subdir' '
309 test_when_finished "rm -rf parent sub" &&
310 git init sub &&
311 echo "(1|2)d(3|4)" >sub/file &&
312 git -C sub add file &&
313 git -C sub commit -m "add file" &&
314 test_tick &&
315
316 git init parent &&
317 mkdir parent/src &&
318 echo "(1|2)d(3|4)" >parent/src/file &&
319 git -C parent add src/file &&
320 git -C parent submodule add ../sub src/sub &&
321 git -C parent submodule add ../sub sub &&
322 git -C parent commit -m "add files and submodules" &&
323 test_tick &&
324
325 # Verify grep from root works
326 cat >expect <<-\EOF &&
327 src/file:(1|2)d(3|4)
328 src/sub/file:(1|2)d(3|4)
329 sub/file:(1|2)d(3|4)
330 EOF
331 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
332 test_cmp expect actual &&
333
334 # Verify grep from a subdir works
335 cat >expect <<-\EOF &&
336 file:(1|2)d(3|4)
337 sub/file:(1|2)d(3|4)
338 EOF
339 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
340 test_cmp expect actual
341 '
342
343 test_incompatible_with_recurse_submodules ()
344 {
345 test_expect_success "--recurse-submodules and $1 are incompatible" "
346 test_must_fail git grep -e. --recurse-submodules $1 2>actual &&
347 test_i18ngrep 'not supported with --recurse-submodules' actual
348 "
349 }
350
351 test_incompatible_with_recurse_submodules --untracked
352
353 test_expect_success 'grep --recurse-submodules --no-index ignores --recurse-submodules' '
354 git grep --recurse-submodules --no-index -e "^(.|.)[\d]" >actual &&
355 cat >expect <<-\EOF &&
356 a:(1|2)d(3|4)
357 submodule/a:(1|2)d(3|4)
358 submodule/sub/a:(1|2)d(3|4)
359 EOF
360 test_cmp expect actual
361 '
362
363 test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
364 # Fixed
365 test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" &&
366 test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" &&
367
368 # Basic
369 git grep -G --recurse-submodules -e "(.|.)[\d]" >actual &&
370 cat >expect <<-\EOF &&
371 a:(1|2)d(3|4)
372 submodule/a:(1|2)d(3|4)
373 submodule/sub/a:(1|2)d(3|4)
374 EOF
375 test_cmp expect actual &&
376 git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
377 test_cmp expect actual &&
378
379 # Extended
380 git grep -E --recurse-submodules -e "(.|.)[\d]" >actual &&
381 cat >expect <<-\EOF &&
382 .gitmodules:[submodule "submodule"]
383 .gitmodules: path = submodule
384 .gitmodules: url = ./submodule
385 a:(1|2)d(3|4)
386 submodule/.gitmodules:[submodule "sub"]
387 submodule/a:(1|2)d(3|4)
388 submodule/sub/a:(1|2)d(3|4)
389 EOF
390 test_cmp expect actual &&
391 git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual &&
392 test_cmp expect actual &&
393 git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual &&
394 test_cmp expect actual &&
395
396 # Perl
397 if test_have_prereq PCRE
398 then
399 git grep -P --recurse-submodules -e "(.|.)[\d]" >actual &&
400 cat >expect <<-\EOF &&
401 a:(1|2)d(3|4)
402 b/b:(3|4)
403 submodule/a:(1|2)d(3|4)
404 submodule/sub/a:(1|2)d(3|4)
405 EOF
406 test_cmp expect actual &&
407 git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
408 test_cmp expect actual
409 fi
410 '
411
412 test_expect_success 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '
413 test_when_finished "git -C submodule checkout .gitmodules" &&
414 rm submodule/.gitmodules &&
415 git grep --recurse-submodules -e "(.|.)[\d]" >actual &&
416 cat >expect <<-\EOF &&
417 a:(1|2)d(3|4)
418 submodule/a:(1|2)d(3|4)
419 submodule/sub/a:(1|2)d(3|4)
420 EOF
421 test_cmp expect actual
422 '
423
424 reset_and_clean () {
425 git reset --hard &&
426 git clean -fd &&
427 git submodule foreach --recursive 'git reset --hard' &&
428 git submodule foreach --recursive 'git clean -fd'
429 }
430
431 test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
432 reset_and_clean &&
433 echo "A modified line in submodule" >>submodule/a &&
434 echo "submodule/a:A modified line in submodule" >expect &&
435 git grep --recurse-submodules "A modified line in submodule" >actual &&
436 test_cmp expect actual
437 '
438
439 test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
440 reset_and_clean &&
441 echo "A modified line in submodule" >>submodule/a &&
442 test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
443 test_must_be_empty actual
444 '
445
446 test_expect_failure 'grep --textconv: superproject .gitattributes does not affect submodules' '
447 reset_and_clean &&
448 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
449 echo "a diff=d2x" >.gitattributes &&
450
451 cat >expect <<-\EOF &&
452 a:(1|2)x(3|4)
453 EOF
454 git grep --textconv --recurse-submodules x >actual &&
455 test_cmp expect actual
456 '
457
458 test_expect_failure 'grep --textconv: superproject .gitattributes (from index) does not affect submodules' '
459 reset_and_clean &&
460 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
461 echo "a diff=d2x" >.gitattributes &&
462 git add .gitattributes &&
463 rm .gitattributes &&
464
465 cat >expect <<-\EOF &&
466 a:(1|2)x(3|4)
467 EOF
468 git grep --textconv --recurse-submodules x >actual &&
469 test_cmp expect actual
470 '
471
472 test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' '
473 reset_and_clean &&
474 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
475 super_info="$(git rev-parse --git-path info)" &&
476 super_attr="$super_info/attributes" &&
477 test_when_finished "rm -f \"$super_attr\"" &&
478 mkdir "$super_info" &&
479 echo "a diff=d2x" >"$super_attr" &&
480
481 cat >expect <<-\EOF &&
482 a:(1|2)x(3|4)
483 EOF
484 git grep --textconv --recurse-submodules x >actual &&
485 test_cmp expect actual
486 '
487
488 # Note: what currently prevents this test from passing is not that the
489 # .gitattributes file from "./submodule" is being ignored, but that it is being
490 # propagated to the nested "./submodule/sub" files.
491 #
492 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes' '
493 reset_and_clean &&
494 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
495 echo "a diff=d2x" >submodule/.gitattributes &&
496
497 cat >expect <<-\EOF &&
498 submodule/a:(1|2)x(3|4)
499 EOF
500 git grep --textconv --recurse-submodules x >actual &&
501 test_cmp expect actual
502 '
503
504 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes (from index)' '
505 reset_and_clean &&
506 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
507 echo "a diff=d2x" >submodule/.gitattributes &&
508 git -C submodule add .gitattributes &&
509 rm submodule/.gitattributes &&
510
511 cat >expect <<-\EOF &&
512 submodule/a:(1|2)x(3|4)
513 EOF
514 git grep --textconv --recurse-submodules x >actual &&
515 test_cmp expect actual
516 '
517
518 test_expect_failure 'grep --textconv correctly reads submodule .git/info/attributes' '
519 reset_and_clean &&
520 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
521
522 submodule_info="$(git -C submodule rev-parse --path-format=absolute --git-path info)" &&
523 submodule_attr="$submodule_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_expect_success 'grep partially-cloned submodule' '
552 # Set up clean superproject and submodule for partial cloning.
553 git init super &&
554 git init super/sub &&
555 (
556 cd super &&
557 test_commit --no-tag "Add file in superproject" \
558 super-file "Some content for super-file" &&
559 test_commit -C sub --no-tag "Add file in submodule" \
560 sub-file "Some content for sub-file" &&
561 git submodule add ./sub &&
562 git commit -m "Add other as submodule sub" &&
563 test_tick &&
564 test_commit -C sub --no-tag --append "Update file in submodule" \
565 sub-file "Some more content for sub-file" &&
566 git add sub &&
567 git commit -m "Update submodule" &&
568 test_tick &&
569 git config --local uploadpack.allowfilter 1 &&
570 git config --local uploadpack.allowanysha1inwant 1 &&
571 git -C sub config --local uploadpack.allowfilter 1 &&
572 git -C sub config --local uploadpack.allowanysha1inwant 1
573 ) &&
574 # Clone the superproject & submodule, then make sure we can lazy-fetch submodule objects.
575 git clone --filter=blob:none --also-filter-submodules \
576 --recurse-submodules "file://$(pwd)/super" partial &&
577 (
578 cd partial &&
579 cat >expect <<-\EOF &&
580 HEAD^:sub/sub-file:Some content for sub-file
581 HEAD^:super-file:Some content for super-file
582 EOF
583
584 GIT_TRACE2_EVENT="$(pwd)/trace2.log" git grep -e content \
585 --recurse-submodules HEAD^ >actual &&
586 test_cmp expect actual &&
587 # Verify that we actually fetched data from the promisor remote:
588 grep \"category\":\"promisor\",\"key\":\"fetch_count\",\"value\":\"1\" trace2.log
589 )
590 '
591
592 test_done