Merge branch 'mh/notes-duplicate-entries'
[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 test_expect_success 'setup directory structure and submodule' '
12         echo "(1|2)d(3|4)" >a &&
13         mkdir b &&
14         echo "(3|4)" >b/b &&
15         git add a b &&
16         git commit -m "add a and b" &&
17         test_tick &&
18         git init submodule &&
19         echo "(1|2)d(3|4)" >submodule/a &&
20         git -C submodule add a &&
21         git -C submodule commit -m "add a" &&
22         git submodule add ./submodule &&
23         git commit -m "added submodule" &&
24         test_tick
25 '
26
27 test_expect_success 'grep correctly finds patterns in a submodule' '
28         cat >expect <<-\EOF &&
29         a:(1|2)d(3|4)
30         b/b:(3|4)
31         submodule/a:(1|2)d(3|4)
32         EOF
33
34         git grep -e "(3|4)" --recurse-submodules >actual &&
35         test_cmp expect actual
36 '
37
38 test_expect_success 'grep finds patterns in a submodule via config' '
39         test_config submodule.recurse true &&
40         # expect from previous test
41         git grep -e "(3|4)" >actual &&
42         test_cmp expect actual
43 '
44
45 test_expect_success 'grep --no-recurse-submodules overrides config' '
46         test_config submodule.recurse true &&
47         cat >expect <<-\EOF &&
48         a:(1|2)d(3|4)
49         b/b:(3|4)
50         EOF
51
52         git grep -e "(3|4)" --no-recurse-submodules >actual &&
53         test_cmp expect actual
54 '
55
56 test_expect_success 'grep and basic pathspecs' '
57         cat >expect <<-\EOF &&
58         submodule/a:(1|2)d(3|4)
59         EOF
60
61         git grep -e. --recurse-submodules -- submodule >actual &&
62         test_cmp expect actual
63 '
64
65 test_expect_success 'grep and nested submodules' '
66         git init submodule/sub &&
67         echo "(1|2)d(3|4)" >submodule/sub/a &&
68         git -C submodule/sub add a &&
69         git -C submodule/sub commit -m "add a" &&
70         test_tick &&
71         git -C submodule submodule add ./sub &&
72         git -C submodule add sub &&
73         git -C submodule commit -m "added sub" &&
74         test_tick &&
75         git add submodule &&
76         git commit -m "updated submodule" &&
77         test_tick &&
78
79         cat >expect <<-\EOF &&
80         a:(1|2)d(3|4)
81         b/b:(3|4)
82         submodule/a:(1|2)d(3|4)
83         submodule/sub/a:(1|2)d(3|4)
84         EOF
85
86         git grep -e "(3|4)" --recurse-submodules >actual &&
87         test_cmp expect actual
88 '
89
90 test_expect_success 'grep and multiple patterns' '
91         cat >expect <<-\EOF &&
92         a:(1|2)d(3|4)
93         submodule/a:(1|2)d(3|4)
94         submodule/sub/a:(1|2)d(3|4)
95         EOF
96
97         git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual &&
98         test_cmp expect actual
99 '
100
101 test_expect_success 'grep and multiple patterns' '
102         cat >expect <<-\EOF &&
103         b/b:(3|4)
104         EOF
105
106         git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual &&
107         test_cmp expect actual
108 '
109
110 test_expect_success 'basic grep tree' '
111         cat >expect <<-\EOF &&
112         HEAD:a:(1|2)d(3|4)
113         HEAD:b/b:(3|4)
114         HEAD:submodule/a:(1|2)d(3|4)
115         HEAD:submodule/sub/a:(1|2)d(3|4)
116         EOF
117
118         git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
119         test_cmp expect actual
120 '
121
122 test_expect_success 'grep tree HEAD^' '
123         cat >expect <<-\EOF &&
124         HEAD^:a:(1|2)d(3|4)
125         HEAD^:b/b:(3|4)
126         HEAD^:submodule/a:(1|2)d(3|4)
127         EOF
128
129         git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
130         test_cmp expect actual
131 '
132
133 test_expect_success 'grep tree HEAD^^' '
134         cat >expect <<-\EOF &&
135         HEAD^^:a:(1|2)d(3|4)
136         HEAD^^:b/b:(3|4)
137         EOF
138
139         git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
140         test_cmp expect actual
141 '
142
143 test_expect_success 'grep tree and pathspecs' '
144         cat >expect <<-\EOF &&
145         HEAD:submodule/a:(1|2)d(3|4)
146         HEAD:submodule/sub/a:(1|2)d(3|4)
147         EOF
148
149         git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual &&
150         test_cmp expect actual
151 '
152
153 test_expect_success 'grep tree and pathspecs' '
154         cat >expect <<-\EOF &&
155         HEAD:submodule/a:(1|2)d(3|4)
156         HEAD:submodule/sub/a:(1|2)d(3|4)
157         EOF
158
159         git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual &&
160         test_cmp expect actual
161 '
162
163 test_expect_success 'grep tree and more pathspecs' '
164         cat >expect <<-\EOF &&
165         HEAD:submodule/a:(1|2)d(3|4)
166         EOF
167
168         git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual &&
169         test_cmp expect actual
170 '
171
172 test_expect_success 'grep tree and more pathspecs' '
173         cat >expect <<-\EOF &&
174         HEAD:submodule/sub/a:(1|2)d(3|4)
175         EOF
176
177         git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
178         test_cmp expect actual
179 '
180
181 test_expect_success !MINGW 'grep recurse submodule colon in name' '
182         git init parent &&
183         test_when_finished "rm -rf parent" &&
184         echo "(1|2)d(3|4)" >"parent/fi:le" &&
185         git -C parent add "fi:le" &&
186         git -C parent commit -m "add fi:le" &&
187         test_tick &&
188
189         git init "su:b" &&
190         test_when_finished "rm -rf su:b" &&
191         echo "(1|2)d(3|4)" >"su:b/fi:le" &&
192         git -C "su:b" add "fi:le" &&
193         git -C "su:b" commit -m "add fi:le" &&
194         test_tick &&
195
196         git -C parent submodule add "../su:b" "su:b" &&
197         git -C parent commit -m "add submodule" &&
198         test_tick &&
199
200         cat >expect <<-\EOF &&
201         fi:le:(1|2)d(3|4)
202         su:b/fi:le:(1|2)d(3|4)
203         EOF
204         git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
205         test_cmp expect actual &&
206
207         cat >expect <<-\EOF &&
208         HEAD:fi:le:(1|2)d(3|4)
209         HEAD:su:b/fi:le:(1|2)d(3|4)
210         EOF
211         git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual &&
212         test_cmp expect actual
213 '
214
215 test_expect_success 'grep history with moved submoules' '
216         git init parent &&
217         test_when_finished "rm -rf parent" &&
218         echo "(1|2)d(3|4)" >parent/file &&
219         git -C parent add file &&
220         git -C parent commit -m "add file" &&
221         test_tick &&
222
223         git init sub &&
224         test_when_finished "rm -rf sub" &&
225         echo "(1|2)d(3|4)" >sub/file &&
226         git -C sub add file &&
227         git -C sub commit -m "add file" &&
228         test_tick &&
229
230         git -C parent submodule add ../sub dir/sub &&
231         git -C parent commit -m "add submodule" &&
232         test_tick &&
233
234         cat >expect <<-\EOF &&
235         dir/sub/file:(1|2)d(3|4)
236         file:(1|2)d(3|4)
237         EOF
238         git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
239         test_cmp expect actual &&
240
241         git -C parent mv dir/sub sub-moved &&
242         git -C parent commit -m "moved submodule" &&
243         test_tick &&
244
245         cat >expect <<-\EOF &&
246         file:(1|2)d(3|4)
247         sub-moved/file:(1|2)d(3|4)
248         EOF
249         git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
250         test_cmp expect actual &&
251
252         cat >expect <<-\EOF &&
253         HEAD^:dir/sub/file:(1|2)d(3|4)
254         HEAD^:file:(1|2)d(3|4)
255         EOF
256         git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
257         test_cmp expect actual
258 '
259
260 test_expect_success 'grep using relative path' '
261         test_when_finished "rm -rf parent sub" &&
262         git init sub &&
263         echo "(1|2)d(3|4)" >sub/file &&
264         git -C sub add file &&
265         git -C sub commit -m "add file" &&
266         test_tick &&
267
268         git init parent &&
269         echo "(1|2)d(3|4)" >parent/file &&
270         git -C parent add file &&
271         mkdir parent/src &&
272         echo "(1|2)d(3|4)" >parent/src/file2 &&
273         git -C parent add src/file2 &&
274         git -C parent submodule add ../sub &&
275         git -C parent commit -m "add files and submodule" &&
276         test_tick &&
277
278         # From top works
279         cat >expect <<-\EOF &&
280         file:(1|2)d(3|4)
281         src/file2:(1|2)d(3|4)
282         sub/file:(1|2)d(3|4)
283         EOF
284         git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
285         test_cmp expect actual &&
286
287         # Relative path to top
288         cat >expect <<-\EOF &&
289         ../file:(1|2)d(3|4)
290         file2:(1|2)d(3|4)
291         ../sub/file:(1|2)d(3|4)
292         EOF
293         git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
294         test_cmp expect actual &&
295
296         # Relative path to submodule
297         cat >expect <<-\EOF &&
298         ../sub/file:(1|2)d(3|4)
299         EOF
300         git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
301         test_cmp expect actual
302 '
303
304 test_expect_success 'grep from a subdir' '
305         test_when_finished "rm -rf parent sub" &&
306         git init sub &&
307         echo "(1|2)d(3|4)" >sub/file &&
308         git -C sub add file &&
309         git -C sub commit -m "add file" &&
310         test_tick &&
311
312         git init parent &&
313         mkdir parent/src &&
314         echo "(1|2)d(3|4)" >parent/src/file &&
315         git -C parent add src/file &&
316         git -C parent submodule add ../sub src/sub &&
317         git -C parent submodule add ../sub sub &&
318         git -C parent commit -m "add files and submodules" &&
319         test_tick &&
320
321         # Verify grep from root works
322         cat >expect <<-\EOF &&
323         src/file:(1|2)d(3|4)
324         src/sub/file:(1|2)d(3|4)
325         sub/file:(1|2)d(3|4)
326         EOF
327         git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
328         test_cmp expect actual &&
329
330         # Verify grep from a subdir works
331         cat >expect <<-\EOF &&
332         file:(1|2)d(3|4)
333         sub/file:(1|2)d(3|4)
334         EOF
335         git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
336         test_cmp expect actual
337 '
338
339 test_incompatible_with_recurse_submodules ()
340 {
341         test_expect_success "--recurse-submodules and $1 are incompatible" "
342                 test_must_fail git grep -e. --recurse-submodules $1 2>actual &&
343                 test_i18ngrep 'not supported with --recurse-submodules' actual
344         "
345 }
346
347 test_incompatible_with_recurse_submodules --untracked
348 test_incompatible_with_recurse_submodules --no-index
349
350 test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
351         # Fixed
352         test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" &&
353         test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" &&
354
355         # Basic
356         git grep -G --recurse-submodules -e "(.|.)[\d]" >actual &&
357         cat >expect <<-\EOF &&
358         a:(1|2)d(3|4)
359         submodule/a:(1|2)d(3|4)
360         submodule/sub/a:(1|2)d(3|4)
361         EOF
362         test_cmp expect actual &&
363         git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
364         test_cmp expect actual &&
365
366         # Extended
367         git grep -E --recurse-submodules -e "(.|.)[\d]" >actual &&
368         cat >expect <<-\EOF &&
369         .gitmodules:[submodule "submodule"]
370         .gitmodules:    path = submodule
371         .gitmodules:    url = ./submodule
372         a:(1|2)d(3|4)
373         submodule/.gitmodules:[submodule "sub"]
374         submodule/a:(1|2)d(3|4)
375         submodule/sub/a:(1|2)d(3|4)
376         EOF
377         test_cmp expect actual &&
378         git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual &&
379         test_cmp expect actual &&
380         git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual &&
381         test_cmp expect actual &&
382
383         # Perl
384         if test_have_prereq PCRE
385         then
386                 git grep -P --recurse-submodules -e "(.|.)[\d]" >actual &&
387                 cat >expect <<-\EOF &&
388                 a:(1|2)d(3|4)
389                 b/b:(3|4)
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=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
395                 test_cmp expect actual
396         fi
397 '
398
399 test_expect_success 'grep --recurse-submodules with submodules without .gitmodules in the working tree' '
400         test_when_finished "git -C submodule checkout .gitmodules" &&
401         rm submodule/.gitmodules &&
402         git grep --recurse-submodules -e "(.|.)[\d]" >actual &&
403         cat >expect <<-\EOF &&
404         a:(1|2)d(3|4)
405         submodule/a:(1|2)d(3|4)
406         submodule/sub/a:(1|2)d(3|4)
407         EOF
408         test_cmp expect actual
409 '
410
411 reset_and_clean () {
412         git reset --hard &&
413         git clean -fd &&
414         git submodule foreach --recursive 'git reset --hard' &&
415         git submodule foreach --recursive 'git clean -fd'
416 }
417
418 test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' '
419         reset_and_clean &&
420         echo "A modified line in submodule" >>submodule/a &&
421         echo "submodule/a:A modified line in submodule" >expect &&
422         git grep --recurse-submodules "A modified line in submodule" >actual &&
423         test_cmp expect actual
424 '
425
426 test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' '
427         reset_and_clean &&
428         echo "A modified line in submodule" >>submodule/a &&
429         test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 &&
430         test_must_be_empty actual
431 '
432 test_done