Merge branch 'ab/make-sparse-for-real'
[git/debian.git] / t / t7814-grep-recurse-submodules.sh
blob058e5d0c966dfd8fe816de8fdc6bcff7f93a70ac
1 #!/bin/sh
3 test_description='Test grep recurse-submodules feature
5 This test verifies the recurse-submodules feature correctly greps across
6 submodules.
9 . ./test-lib.sh
11 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
12 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
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
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
37 git grep -e "(3|4)" --recurse-submodules >actual &&
38 test_cmp expect actual
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
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
55 git grep -e "(3|4)" --no-recurse-submodules >actual &&
56 test_cmp expect actual
59 test_expect_success 'grep and basic pathspecs' '
60 cat >expect <<-\EOF &&
61 submodule/a:(1|2)d(3|4)
62 EOF
64 git grep -e. --recurse-submodules -- submodule >actual &&
65 test_cmp expect actual
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 &&
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
89 git grep -e "(3|4)" --recurse-submodules >actual &&
90 test_cmp expect actual
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
100 git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual &&
101 test_cmp expect actual
104 test_expect_success 'grep and multiple patterns' '
105 cat >expect <<-\EOF &&
106 b/b:(3|4)
109 git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual &&
110 test_cmp expect actual
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)
121 git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
122 test_cmp expect actual
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)
132 git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
133 test_cmp expect actual
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)
142 git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
143 test_cmp expect actual
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)
152 git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual &&
153 test_cmp expect actual
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)
162 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual &&
163 test_cmp expect actual
166 test_expect_success 'grep tree and more pathspecs' '
167 cat >expect <<-\EOF &&
168 HEAD:submodule/a:(1|2)d(3|4)
171 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual &&
172 test_cmp expect actual
175 test_expect_success 'grep tree and more pathspecs' '
176 cat >expect <<-\EOF &&
177 HEAD:submodule/sub/a:(1|2)d(3|4)
180 git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
181 test_cmp expect actual
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 &&
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 &&
199 git -C parent submodule add "../su:b" "su:b" &&
200 git -C parent commit -m "add submodule" &&
201 test_tick &&
203 cat >expect <<-\EOF &&
204 fi:le:(1|2)d(3|4)
205 su:b/fi:le:(1|2)d(3|4)
207 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
208 test_cmp expect actual &&
210 cat >expect <<-\EOF &&
211 HEAD:fi:le:(1|2)d(3|4)
212 HEAD:su:b/fi:le:(1|2)d(3|4)
214 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual &&
215 test_cmp expect actual
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 &&
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 &&
233 git -C parent submodule add ../sub dir/sub &&
234 git -C parent commit -m "add submodule" &&
235 test_tick &&
237 cat >expect <<-\EOF &&
238 dir/sub/file:(1|2)d(3|4)
239 file:(1|2)d(3|4)
241 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
242 test_cmp expect actual &&
244 git -C parent mv dir/sub sub-moved &&
245 git -C parent commit -m "moved submodule" &&
246 test_tick &&
248 cat >expect <<-\EOF &&
249 file:(1|2)d(3|4)
250 sub-moved/file:(1|2)d(3|4)
252 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
253 test_cmp expect actual &&
255 cat >expect <<-\EOF &&
256 HEAD^:dir/sub/file:(1|2)d(3|4)
257 HEAD^:file:(1|2)d(3|4)
259 git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
260 test_cmp expect actual
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 &&
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 &&
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)
287 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
288 test_cmp expect actual &&
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)
296 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
297 test_cmp expect actual &&
299 # Relative path to submodule
300 cat >expect <<-\EOF &&
301 ../sub/file:(1|2)d(3|4)
303 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
304 test_cmp expect actual
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 &&
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 &&
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)
330 git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
331 test_cmp expect actual &&
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)
338 git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
339 test_cmp expect actual
342 test_incompatible_with_recurse_submodules ()
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
350 test_incompatible_with_recurse_submodules --untracked
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)
359 test_cmp expect actual
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]" &&
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)
374 test_cmp expect actual &&
375 git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
376 test_cmp expect actual &&
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)
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 &&
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)
405 test_cmp expect actual &&
406 git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
407 test_cmp expect actual
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)
420 test_cmp expect actual
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'
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
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
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 &&
450 cat >expect <<-\EOF &&
451 a:(1|2)x(3|4)
453 git grep --textconv --recurse-submodules x >actual &&
454 test_cmp expect actual
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 &&
464 cat >expect <<-\EOF &&
465 a:(1|2)x(3|4)
467 git grep --textconv --recurse-submodules x >actual &&
468 test_cmp expect actual
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" &&
478 cat >expect <<-\EOF &&
479 a:(1|2)x(3|4)
481 git grep --textconv --recurse-submodules x >actual &&
482 test_cmp expect actual
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.
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 &&
494 cat >expect <<-\EOF &&
495 submodule/a:(1|2)x(3|4)
497 git grep --textconv --recurse-submodules x >actual &&
498 test_cmp expect actual
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 &&
508 cat >expect <<-\EOF &&
509 submodule/a:(1|2)x(3|4)
511 git grep --textconv --recurse-submodules x >actual &&
512 test_cmp expect actual
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/\"" &&
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" &&
523 cat >expect <<-\EOF &&
524 submodule/a:(1|2)x(3|4)
526 git grep --textconv --recurse-submodules x >actual &&
527 test_cmp expect actual
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 &&
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 &&
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"
547 test_done