]> git.ipfire.org Git - thirdparty/git.git/blob - t/t7814-grep-recurse-submodules.sh
clone: allow "--bare" with "-o"
[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 git -C parent submodule add "../su:b" "su:b" &&
200 git -C parent commit -m "add submodule" &&
201 test_tick &&
202
203 cat >expect <<-\EOF &&
204 fi:le:(1|2)d(3|4)
205 su:b/fi:le:(1|2)d(3|4)
206 EOF
207 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
208 test_cmp expect actual &&
209
210 cat >expect <<-\EOF &&
211 HEAD:fi:le:(1|2)d(3|4)
212 HEAD:su:b/fi:le:(1|2)d(3|4)
213 EOF
214 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual &&
215 test_cmp expect actual
216 '
217
218 test_expect_success 'grep history with moved submoules' '
219 git init parent &&
220 test_when_finished "rm -rf parent" &&
221 echo "(1|2)d(3|4)" >parent/file &&
222 git -C parent add file &&
223 git -C parent commit -m "add file" &&
224 test_tick &&
225
226 git init sub &&
227 test_when_finished "rm -rf sub" &&
228 echo "(1|2)d(3|4)" >sub/file &&
229 git -C sub add file &&
230 git -C sub commit -m "add file" &&
231 test_tick &&
232
233 git -C parent submodule add ../sub dir/sub &&
234 git -C parent commit -m "add submodule" &&
235 test_tick &&
236
237 cat >expect <<-\EOF &&
238 dir/sub/file:(1|2)d(3|4)
239 file:(1|2)d(3|4)
240 EOF
241 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
242 test_cmp expect actual &&
243
244 git -C parent mv dir/sub sub-moved &&
245 git -C parent commit -m "moved submodule" &&
246 test_tick &&
247
248 cat >expect <<-\EOF &&
249 file:(1|2)d(3|4)
250 sub-moved/file:(1|2)d(3|4)
251 EOF
252 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
253 test_cmp expect actual &&
254
255 cat >expect <<-\EOF &&
256 HEAD^:dir/sub/file:(1|2)d(3|4)
257 HEAD^:file:(1|2)d(3|4)
258 EOF
259 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
260 test_cmp expect actual
261 '
262
263 test_expect_success 'grep using relative path' '
264 test_when_finished "rm -rf parent sub" &&
265 git init sub &&
266 echo "(1|2)d(3|4)" >sub/file &&
267 git -C sub add file &&
268 git -C sub commit -m "add file" &&
269 test_tick &&
270
271 git init parent &&
272 echo "(1|2)d(3|4)" >parent/file &&
273 git -C parent add file &&
274 mkdir parent/src &&
275 echo "(1|2)d(3|4)" >parent/src/file2 &&
276 git -C parent add src/file2 &&
277 git -C parent submodule add ../sub &&
278 git -C parent commit -m "add files and submodule" &&
279 test_tick &&
280
281 # From top works
282 cat >expect <<-\EOF &&
283 file:(1|2)d(3|4)
284 src/file2:(1|2)d(3|4)
285 sub/file:(1|2)d(3|4)
286 EOF
287 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
288 test_cmp expect actual &&
289
290 # Relative path to top
291 cat >expect <<-\EOF &&
292 ../file:(1|2)d(3|4)
293 file2:(1|2)d(3|4)
294 ../sub/file:(1|2)d(3|4)
295 EOF
296 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
297 test_cmp expect actual &&
298
299 # Relative path to submodule
300 cat >expect <<-\EOF &&
301 ../sub/file:(1|2)d(3|4)
302 EOF
303 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
304 test_cmp expect actual
305 '
306
307 test_expect_success 'grep from a subdir' '
308 test_when_finished "rm -rf parent sub" &&
309 git init sub &&
310 echo "(1|2)d(3|4)" >sub/file &&
311 git -C sub add file &&
312 git -C sub commit -m "add file" &&
313 test_tick &&
314
315 git init parent &&
316 mkdir parent/src &&
317 echo "(1|2)d(3|4)" >parent/src/file &&
318 git -C parent add src/file &&
319 git -C parent submodule add ../sub src/sub &&
320 git -C parent submodule add ../sub sub &&
321 git -C parent commit -m "add files and submodules" &&
322 test_tick &&
323
324 # Verify grep from root works
325 cat >expect <<-\EOF &&
326 src/file:(1|2)d(3|4)
327 src/sub/file:(1|2)d(3|4)
328 sub/file:(1|2)d(3|4)
329 EOF
330 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
331 test_cmp expect actual &&
332
333 # Verify grep from a subdir works
334 cat >expect <<-\EOF &&
335 file:(1|2)d(3|4)
336 sub/file:(1|2)d(3|4)
337 EOF
338 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
339 test_cmp expect actual
340 '
341
342 test_incompatible_with_recurse_submodules ()
343 {
344 test_expect_success "--recurse-submodules and $1 are incompatible" "
345 test_must_fail git grep -e. --recurse-submodules $1 2>actual &&
346 test_i18ngrep 'not supported with --recurse-submodules' actual
347 "
348 }
349
350 test_incompatible_with_recurse_submodules --untracked
351
352 test_expect_success 'grep --recurse-submodules --no-index ignores --recurse-submodules' '
353 git grep --recurse-submodules --no-index -e "^(.|.)[\d]" >actual &&
354 cat >expect <<-\EOF &&
355 a:(1|2)d(3|4)
356 submodule/a:(1|2)d(3|4)
357 submodule/sub/a:(1|2)d(3|4)
358 EOF
359 test_cmp expect actual
360 '
361
362 test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
363 # Fixed
364 test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" &&
365 test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" &&
366
367 # Basic
368 git grep -G --recurse-submodules -e "(.|.)[\d]" >actual &&
369 cat >expect <<-\EOF &&
370 a:(1|2)d(3|4)
371 submodule/a:(1|2)d(3|4)
372 submodule/sub/a:(1|2)d(3|4)
373 EOF
374 test_cmp expect actual &&
375 git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
376 test_cmp expect actual &&
377
378 # Extended
379 git grep -E --recurse-submodules -e "(.|.)[\d]" >actual &&
380 cat >expect <<-\EOF &&
381 .gitmodules:[submodule "submodule"]
382 .gitmodules: path = submodule
383 .gitmodules: url = ./submodule
384 a:(1|2)d(3|4)
385 submodule/.gitmodules:[submodule "sub"]
386 submodule/a:(1|2)d(3|4)
387 submodule/sub/a:(1|2)d(3|4)
388 EOF
389 test_cmp expect actual &&
390 git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual &&
391 test_cmp expect actual &&
392 git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual &&
393 test_cmp expect actual &&
394
395 # Perl
396 if test_have_prereq PCRE
397 then
398 git grep -P --recurse-submodules -e "(.|.)[\d]" >actual &&
399 cat >expect <<-\EOF &&
400 a:(1|2)d(3|4)
401 b/b:(3|4)
402 submodule/a:(1|2)d(3|4)
403 submodule/sub/a:(1|2)d(3|4)
404 EOF
405 test_cmp expect actual &&
406 git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
407 test_cmp expect actual
408 fi
409 '
410
411 test_expect_success 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '
412 test_when_finished "git -C submodule checkout .gitmodules" &&
413 rm submodule/.gitmodules &&
414 git grep --recurse-submodules -e "(.|.)[\d]" >actual &&
415 cat >expect <<-\EOF &&
416 a:(1|2)d(3|4)
417 submodule/a:(1|2)d(3|4)
418 submodule/sub/a:(1|2)d(3|4)
419 EOF
420 test_cmp expect actual
421 '
422
423 reset_and_clean () {
424 git reset --hard &&
425 git clean -fd &&
426 git submodule foreach --recursive 'git reset --hard' &&
427 git submodule foreach --recursive 'git clean -fd'
428 }
429
430 test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
431 reset_and_clean &&
432 echo "A modified line in submodule" >>submodule/a &&
433 echo "submodule/a:A modified line in submodule" >expect &&
434 git grep --recurse-submodules "A modified line in submodule" >actual &&
435 test_cmp expect actual
436 '
437
438 test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
439 reset_and_clean &&
440 echo "A modified line in submodule" >>submodule/a &&
441 test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
442 test_must_be_empty actual
443 '
444
445 test_expect_failure 'grep --textconv: superproject .gitattributes does not affect submodules' '
446 reset_and_clean &&
447 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
448 echo "a diff=d2x" >.gitattributes &&
449
450 cat >expect <<-\EOF &&
451 a:(1|2)x(3|4)
452 EOF
453 git grep --textconv --recurse-submodules x >actual &&
454 test_cmp expect actual
455 '
456
457 test_expect_failure 'grep --textconv: superproject .gitattributes (from index) does not affect submodules' '
458 reset_and_clean &&
459 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
460 echo "a diff=d2x" >.gitattributes &&
461 git add .gitattributes &&
462 rm .gitattributes &&
463
464 cat >expect <<-\EOF &&
465 a:(1|2)x(3|4)
466 EOF
467 git grep --textconv --recurse-submodules x >actual &&
468 test_cmp expect actual
469 '
470
471 test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' '
472 reset_and_clean &&
473 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
474 super_attr="$(git rev-parse --git-path info/attributes)" &&
475 test_when_finished "rm -f \"$super_attr\"" &&
476 echo "a diff=d2x" >"$super_attr" &&
477
478 cat >expect <<-\EOF &&
479 a:(1|2)x(3|4)
480 EOF
481 git grep --textconv --recurse-submodules x >actual &&
482 test_cmp expect actual
483 '
484
485 # Note: what currently prevents this test from passing is not that the
486 # .gitattributes file from "./submodule" is being ignored, but that it is being
487 # propagated to the nested "./submodule/sub" files.
488 #
489 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes' '
490 reset_and_clean &&
491 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
492 echo "a diff=d2x" >submodule/.gitattributes &&
493
494 cat >expect <<-\EOF &&
495 submodule/a:(1|2)x(3|4)
496 EOF
497 git grep --textconv --recurse-submodules x >actual &&
498 test_cmp expect actual
499 '
500
501 test_expect_failure 'grep --textconv correctly reads submodule .gitattributes (from index)' '
502 reset_and_clean &&
503 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
504 echo "a diff=d2x" >submodule/.gitattributes &&
505 git -C submodule add .gitattributes &&
506 rm submodule/.gitattributes &&
507
508 cat >expect <<-\EOF &&
509 submodule/a:(1|2)x(3|4)
510 EOF
511 git grep --textconv --recurse-submodules x >actual &&
512 test_cmp expect actual
513 '
514
515 test_expect_failure 'grep --textconv correctly reads submodule .git/info/attributes' '
516 reset_and_clean &&
517 test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" &&
518
519 submodule_attr="$(git -C submodule rev-parse --path-format=absolute --git-path info/attributes)" &&
520 test_when_finished "rm -f \"$submodule_attr\"" &&
521 echo "a diff=d2x" >"$submodule_attr" &&
522
523 cat >expect <<-\EOF &&
524 submodule/a:(1|2)x(3|4)
525 EOF
526 git grep --textconv --recurse-submodules x >actual &&
527 test_cmp expect actual
528 '
529
530 test_expect_failure 'grep saves textconv cache in the appropriate repository' '
531 reset_and_clean &&
532 test_config_global diff.d2x_cached.textconv "sed -e \"s/d/x/\"" &&
533 test_config_global diff.d2x_cached.cachetextconv true &&
534 echo "a diff=d2x_cached" >submodule/.gitattributes &&
535
536 # We only read/write to the textconv cache when grepping from an OID,
537 # as the working tree file might have modifications.
538 git grep --textconv --cached --recurse-submodules x &&
539
540 super_textconv_cache="$(git rev-parse --git-path refs/notes/textconv/d2x_cached)" &&
541 sub_textconv_cache="$(git -C submodule rev-parse \
542 --path-format=absolute --git-path refs/notes/textconv/d2x_cached)" &&
543 test_path_is_missing "$super_textconv_cache" &&
544 test_path_is_file "$sub_textconv_cache"
545 '
546
547 test_expect_success 'grep partially-cloned submodule' '
548 # Set up clean superproject and submodule for partial cloning.
549 git init super &&
550 git init super/sub &&
551 (
552 cd super &&
553 test_commit --no-tag "Add file in superproject" \
554 super-file "Some content for super-file" &&
555 test_commit -C sub --no-tag "Add file in submodule" \
556 sub-file "Some content for sub-file" &&
557 git submodule add ./sub &&
558 git commit -m "Add other as submodule sub" &&
559 test_tick &&
560 test_commit -C sub --no-tag --append "Update file in submodule" \
561 sub-file "Some more content for sub-file" &&
562 git add sub &&
563 git commit -m "Update submodule" &&
564 test_tick &&
565 git config --local uploadpack.allowfilter 1 &&
566 git config --local uploadpack.allowanysha1inwant 1 &&
567 git -C sub config --local uploadpack.allowfilter 1 &&
568 git -C sub config --local uploadpack.allowanysha1inwant 1
569 ) &&
570 # Clone the superproject & submodule, then make sure we can lazy-fetch submodule objects.
571 git clone --filter=blob:none --also-filter-submodules \
572 --recurse-submodules "file://$(pwd)/super" partial &&
573 (
574 cd partial &&
575 cat >expect <<-\EOF &&
576 HEAD^:sub/sub-file:Some content for sub-file
577 HEAD^:super-file:Some content for super-file
578 EOF
579
580 GIT_TRACE2_EVENT="$(pwd)/trace2.log" git grep -e content \
581 --recurse-submodules HEAD^ >actual &&
582 test_cmp expect actual &&
583 # Verify that we actually fetched data from the promisor remote:
584 grep \"category\":\"promisor\",\"key\":\"fetch_count\",\"value\":\"1\" trace2.log
585 )
586 '
587
588 test_done