Merge branch 'ma/doc-pack-format-varint-for-sizes'
[git] / t / t5526-fetch-submodules.sh
1 #!/bin/sh
2 # Copyright (c) 2010, Jens Lehmann
3
4 test_description='Recursive "git fetch" for submodules'
5
6 . ./test-lib.sh
7
8 pwd=$(pwd)
9
10 add_upstream_commit() {
11         (
12                 cd submodule &&
13                 head1=$(git rev-parse --short HEAD) &&
14                 echo new >> subfile &&
15                 test_tick &&
16                 git add subfile &&
17                 git commit -m new subfile &&
18                 head2=$(git rev-parse --short HEAD) &&
19                 echo "Fetching submodule submodule" > ../expect.err &&
20                 echo "From $pwd/submodule" >> ../expect.err &&
21                 echo "   $head1..$head2  sub        -> origin/sub" >> ../expect.err
22         ) &&
23         (
24                 cd deepsubmodule &&
25                 head1=$(git rev-parse --short HEAD) &&
26                 echo new >> deepsubfile &&
27                 test_tick &&
28                 git add deepsubfile &&
29                 git commit -m new deepsubfile &&
30                 head2=$(git rev-parse --short HEAD) &&
31                 echo "Fetching submodule submodule/subdir/deepsubmodule" >> ../expect.err
32                 echo "From $pwd/deepsubmodule" >> ../expect.err &&
33                 echo "   $head1..$head2  deep       -> origin/deep" >> ../expect.err
34         )
35 }
36
37 test_expect_success setup '
38         mkdir deepsubmodule &&
39         (
40                 cd deepsubmodule &&
41                 git init &&
42                 echo deepsubcontent > deepsubfile &&
43                 git add deepsubfile &&
44                 git commit -m new deepsubfile &&
45                 git branch -M deep
46         ) &&
47         mkdir submodule &&
48         (
49                 cd submodule &&
50                 git init &&
51                 echo subcontent > subfile &&
52                 git add subfile &&
53                 git submodule add "$pwd/deepsubmodule" subdir/deepsubmodule &&
54                 git commit -a -m new &&
55                 git branch -M sub
56         ) &&
57         git submodule add "$pwd/submodule" submodule &&
58         git commit -am initial &&
59         git branch -M super &&
60         git clone . downstream &&
61         (
62                 cd downstream &&
63                 git submodule update --init --recursive
64         )
65 '
66
67 test_expect_success "fetch --recurse-submodules recurses into submodules" '
68         add_upstream_commit &&
69         (
70                 cd downstream &&
71                 git fetch --recurse-submodules >../actual.out 2>../actual.err
72         ) &&
73         test_must_be_empty actual.out &&
74         test_i18ncmp expect.err actual.err
75 '
76
77 test_expect_success "submodule.recurse option triggers recursive fetch" '
78         add_upstream_commit &&
79         (
80                 cd downstream &&
81                 git -c submodule.recurse fetch >../actual.out 2>../actual.err
82         ) &&
83         test_must_be_empty actual.out &&
84         test_i18ncmp expect.err actual.err
85 '
86
87 test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
88         add_upstream_commit &&
89         (
90                 cd downstream &&
91                 GIT_TRACE="$TRASH_DIRECTORY/trace.out" git fetch --recurse-submodules -j2 2>../actual.err
92         ) &&
93         test_must_be_empty actual.out &&
94         test_i18ncmp expect.err actual.err &&
95         grep "2 tasks" trace.out
96 '
97
98 test_expect_success "fetch alone only fetches superproject" '
99         add_upstream_commit &&
100         (
101                 cd downstream &&
102                 git fetch >../actual.out 2>../actual.err
103         ) &&
104         test_must_be_empty actual.out &&
105         test_must_be_empty actual.err
106 '
107
108 test_expect_success "fetch --no-recurse-submodules only fetches superproject" '
109         (
110                 cd downstream &&
111                 git fetch --no-recurse-submodules >../actual.out 2>../actual.err
112         ) &&
113         test_must_be_empty actual.out &&
114         test_must_be_empty actual.err
115 '
116
117 test_expect_success "using fetchRecurseSubmodules=true in .gitmodules recurses into submodules" '
118         (
119                 cd downstream &&
120                 git config -f .gitmodules submodule.submodule.fetchRecurseSubmodules true &&
121                 git fetch >../actual.out 2>../actual.err
122         ) &&
123         test_must_be_empty actual.out &&
124         test_i18ncmp expect.err actual.err
125 '
126
127 test_expect_success "--no-recurse-submodules overrides .gitmodules config" '
128         add_upstream_commit &&
129         (
130                 cd downstream &&
131                 git fetch --no-recurse-submodules >../actual.out 2>../actual.err
132         ) &&
133         test_must_be_empty actual.out &&
134         test_must_be_empty actual.err
135 '
136
137 test_expect_success "using fetchRecurseSubmodules=false in .git/config overrides setting in .gitmodules" '
138         (
139                 cd downstream &&
140                 git config submodule.submodule.fetchRecurseSubmodules false &&
141                 git fetch >../actual.out 2>../actual.err
142         ) &&
143         test_must_be_empty actual.out &&
144         test_must_be_empty actual.err
145 '
146
147 test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setting from .git/config" '
148         (
149                 cd downstream &&
150                 git fetch --recurse-submodules >../actual.out 2>../actual.err &&
151                 git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules &&
152                 git config --unset submodule.submodule.fetchRecurseSubmodules
153         ) &&
154         test_must_be_empty actual.out &&
155         test_i18ncmp expect.err actual.err
156 '
157
158 test_expect_success "--quiet propagates to submodules" '
159         (
160                 cd downstream &&
161                 git fetch --recurse-submodules --quiet >../actual.out 2>../actual.err
162         ) &&
163         test_must_be_empty actual.out &&
164         test_must_be_empty actual.err
165 '
166
167 test_expect_success "--quiet propagates to parallel submodules" '
168         (
169                 cd downstream &&
170                 git fetch --recurse-submodules -j 2 --quiet  >../actual.out 2>../actual.err
171         ) &&
172         test_must_be_empty actual.out &&
173         test_must_be_empty actual.err
174 '
175
176 test_expect_success "--dry-run propagates to submodules" '
177         add_upstream_commit &&
178         (
179                 cd downstream &&
180                 git fetch --recurse-submodules --dry-run >../actual.out 2>../actual.err
181         ) &&
182         test_must_be_empty actual.out &&
183         test_i18ncmp expect.err actual.err
184 '
185
186 test_expect_success "Without --dry-run propagates to submodules" '
187         (
188                 cd downstream &&
189                 git fetch --recurse-submodules >../actual.out 2>../actual.err
190         ) &&
191         test_must_be_empty actual.out &&
192         test_i18ncmp expect.err actual.err
193 '
194
195 test_expect_success "recurseSubmodules=true propagates into submodules" '
196         add_upstream_commit &&
197         (
198                 cd downstream &&
199                 git config fetch.recurseSubmodules true &&
200                 git fetch >../actual.out 2>../actual.err
201         ) &&
202         test_must_be_empty actual.out &&
203         test_i18ncmp expect.err actual.err
204 '
205
206 test_expect_success "--recurse-submodules overrides config in submodule" '
207         add_upstream_commit &&
208         (
209                 cd downstream &&
210                 (
211                         cd submodule &&
212                         git config fetch.recurseSubmodules false
213                 ) &&
214                 git fetch --recurse-submodules >../actual.out 2>../actual.err
215         ) &&
216         test_must_be_empty actual.out &&
217         test_i18ncmp expect.err actual.err
218 '
219
220 test_expect_success "--no-recurse-submodules overrides config setting" '
221         add_upstream_commit &&
222         (
223                 cd downstream &&
224                 git config fetch.recurseSubmodules true &&
225                 git fetch --no-recurse-submodules >../actual.out 2>../actual.err
226         ) &&
227         test_must_be_empty actual.out &&
228         test_must_be_empty actual.err
229 '
230
231 test_expect_success "Recursion doesn't happen when no new commits are fetched in the superproject" '
232         (
233                 cd downstream &&
234                 (
235                         cd submodule &&
236                         git config --unset fetch.recurseSubmodules
237                 ) &&
238                 git config --unset fetch.recurseSubmodules &&
239                 git fetch >../actual.out 2>../actual.err
240         ) &&
241         test_must_be_empty actual.out &&
242         test_must_be_empty actual.err
243 '
244
245 test_expect_success "Recursion stops when no new submodule commits are fetched" '
246         head1=$(git rev-parse --short HEAD) &&
247         git add submodule &&
248         git commit -m "new submodule" &&
249         head2=$(git rev-parse --short HEAD) &&
250         echo "From $pwd/." > expect.err.sub &&
251         echo "   $head1..$head2  super      -> origin/super" >>expect.err.sub &&
252         head -3 expect.err >> expect.err.sub &&
253         (
254                 cd downstream &&
255                 git fetch >../actual.out 2>../actual.err
256         ) &&
257         test_i18ncmp expect.err.sub actual.err &&
258         test_must_be_empty actual.out
259 '
260
261 test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" '
262         add_upstream_commit &&
263         head1=$(git rev-parse --short HEAD) &&
264         echo a > file &&
265         git add file &&
266         git commit -m "new file" &&
267         head2=$(git rev-parse --short HEAD) &&
268         echo "From $pwd/." > expect.err.file &&
269         echo "   $head1..$head2  super      -> origin/super" >> expect.err.file &&
270         (
271                 cd downstream &&
272                 git fetch >../actual.out 2>../actual.err
273         ) &&
274         test_must_be_empty actual.out &&
275         test_i18ncmp expect.err.file actual.err
276 '
277
278 test_expect_success "Recursion picks up config in submodule" '
279         (
280                 cd downstream &&
281                 git fetch --recurse-submodules &&
282                 (
283                         cd submodule &&
284                         git config fetch.recurseSubmodules true
285                 )
286         ) &&
287         add_upstream_commit &&
288         head1=$(git rev-parse --short HEAD) &&
289         git add submodule &&
290         git commit -m "new submodule" &&
291         head2=$(git rev-parse --short HEAD) &&
292         echo "From $pwd/." > expect.err.sub &&
293         echo "   $head1..$head2  super      -> origin/super" >> expect.err.sub &&
294         cat expect.err >> expect.err.sub &&
295         (
296                 cd downstream &&
297                 git fetch >../actual.out 2>../actual.err &&
298                 (
299                         cd submodule &&
300                         git config --unset fetch.recurseSubmodules
301                 )
302         ) &&
303         test_i18ncmp expect.err.sub actual.err &&
304         test_must_be_empty actual.out
305 '
306
307 test_expect_success "Recursion picks up all submodules when necessary" '
308         add_upstream_commit &&
309         (
310                 cd submodule &&
311                 (
312                         cd subdir/deepsubmodule &&
313                         git fetch &&
314                         git checkout -q FETCH_HEAD
315                 ) &&
316                 head1=$(git rev-parse --short HEAD^) &&
317                 git add subdir/deepsubmodule &&
318                 git commit -m "new deepsubmodule" &&
319                 head2=$(git rev-parse --short HEAD) &&
320                 echo "Fetching submodule submodule" > ../expect.err.sub &&
321                 echo "From $pwd/submodule" >> ../expect.err.sub &&
322                 echo "   $head1..$head2  sub        -> origin/sub" >> ../expect.err.sub
323         ) &&
324         head1=$(git rev-parse --short HEAD) &&
325         git add submodule &&
326         git commit -m "new submodule" &&
327         head2=$(git rev-parse --short HEAD) &&
328         echo "From $pwd/." > expect.err.2 &&
329         echo "   $head1..$head2  super      -> origin/super" >> expect.err.2 &&
330         cat expect.err.sub >> expect.err.2 &&
331         tail -3 expect.err >> expect.err.2 &&
332         (
333                 cd downstream &&
334                 git fetch >../actual.out 2>../actual.err
335         ) &&
336         test_i18ncmp expect.err.2 actual.err &&
337         test_must_be_empty actual.out
338 '
339
340 test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
341         add_upstream_commit &&
342         (
343                 cd submodule &&
344                 (
345                         cd subdir/deepsubmodule &&
346                         git fetch &&
347                         git checkout -q FETCH_HEAD
348                 ) &&
349                 head1=$(git rev-parse --short HEAD^) &&
350                 git add subdir/deepsubmodule &&
351                 git commit -m "new deepsubmodule" &&
352                 head2=$(git rev-parse --short HEAD) &&
353                 echo Fetching submodule submodule > ../expect.err.sub &&
354                 echo "From $pwd/submodule" >> ../expect.err.sub &&
355                 echo "   $head1..$head2  sub        -> origin/sub" >> ../expect.err.sub
356         ) &&
357         (
358                 cd downstream &&
359                 git config fetch.recurseSubmodules true &&
360                 git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
361                 git config --unset fetch.recurseSubmodules
362         ) &&
363         test_must_be_empty actual.out &&
364         test_must_be_empty actual.err
365 '
366
367 test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
368         head1=$(git rev-parse --short HEAD) &&
369         git add submodule &&
370         git commit -m "new submodule" &&
371         head2=$(git rev-parse --short HEAD) &&
372         tail -3 expect.err > expect.err.deepsub &&
373         echo "From $pwd/." > expect.err &&
374         echo "   $head1..$head2  super      -> origin/super" >>expect.err &&
375         cat expect.err.sub >> expect.err &&
376         cat expect.err.deepsub >> expect.err &&
377         (
378                 cd downstream &&
379                 git config fetch.recurseSubmodules false &&
380                 (
381                         cd submodule &&
382                         git config -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive false
383                 ) &&
384                 git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err &&
385                 git config --unset fetch.recurseSubmodules &&
386                 (
387                         cd submodule &&
388                         git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive
389                 )
390         ) &&
391         test_must_be_empty actual.out &&
392         test_i18ncmp expect.err actual.err
393 '
394
395 test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
396         add_upstream_commit &&
397         head1=$(git rev-parse --short HEAD) &&
398         echo a >> file &&
399         git add file &&
400         git commit -m "new file" &&
401         head2=$(git rev-parse --short HEAD) &&
402         echo "From $pwd/." > expect.err.file &&
403         echo "   $head1..$head2  super      -> origin/super" >> expect.err.file &&
404         (
405                 cd downstream &&
406                 git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err
407         ) &&
408         test_must_be_empty actual.out &&
409         test_i18ncmp expect.err.file actual.err
410 '
411
412 test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config" '
413         (
414                 cd downstream &&
415                 git fetch --recurse-submodules
416         ) &&
417         add_upstream_commit &&
418         git config --global fetch.recurseSubmodules false &&
419         head1=$(git rev-parse --short HEAD) &&
420         git add submodule &&
421         git commit -m "new submodule" &&
422         head2=$(git rev-parse --short HEAD) &&
423         echo "From $pwd/." > expect.err.2 &&
424         echo "   $head1..$head2  super      -> origin/super" >>expect.err.2 &&
425         head -3 expect.err >> expect.err.2 &&
426         (
427                 cd downstream &&
428                 git config fetch.recurseSubmodules on-demand &&
429                 git fetch >../actual.out 2>../actual.err
430         ) &&
431         git config --global --unset fetch.recurseSubmodules &&
432         (
433                 cd downstream &&
434                 git config --unset fetch.recurseSubmodules
435         ) &&
436         test_must_be_empty actual.out &&
437         test_i18ncmp expect.err.2 actual.err
438 '
439
440 test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' overrides fetch.recurseSubmodules" '
441         (
442                 cd downstream &&
443                 git fetch --recurse-submodules
444         ) &&
445         add_upstream_commit &&
446         git config fetch.recurseSubmodules false &&
447         head1=$(git rev-parse --short HEAD) &&
448         git add submodule &&
449         git commit -m "new submodule" &&
450         head2=$(git rev-parse --short HEAD) &&
451         echo "From $pwd/." > expect.err.2 &&
452         echo "   $head1..$head2  super      -> origin/super" >>expect.err.2 &&
453         head -3 expect.err >> expect.err.2 &&
454         (
455                 cd downstream &&
456                 git config submodule.submodule.fetchRecurseSubmodules on-demand &&
457                 git fetch >../actual.out 2>../actual.err
458         ) &&
459         git config --unset fetch.recurseSubmodules &&
460         (
461                 cd downstream &&
462                 git config --unset submodule.submodule.fetchRecurseSubmodules
463         ) &&
464         test_must_be_empty actual.out &&
465         test_i18ncmp expect.err.2 actual.err
466 '
467
468 test_expect_success "don't fetch submodule when newly recorded commits are already present" '
469         (
470                 cd submodule &&
471                 git checkout -q HEAD^^
472         ) &&
473         head1=$(git rev-parse --short HEAD) &&
474         git add submodule &&
475         git commit -m "submodule rewound" &&
476         head2=$(git rev-parse --short HEAD) &&
477         echo "From $pwd/." > expect.err &&
478         echo "   $head1..$head2  super      -> origin/super" >> expect.err &&
479         (
480                 cd downstream &&
481                 git fetch >../actual.out 2>../actual.err
482         ) &&
483         test_must_be_empty actual.out &&
484         test_i18ncmp expect.err actual.err &&
485         (
486                 cd submodule &&
487                 git checkout -q sub
488         )
489 '
490
491 test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .gitmodules entry" '
492         (
493                 cd downstream &&
494                 git fetch --recurse-submodules
495         ) &&
496         add_upstream_commit &&
497         head1=$(git rev-parse --short HEAD) &&
498         git add submodule &&
499         git rm .gitmodules &&
500         git commit -m "new submodule without .gitmodules" &&
501         head2=$(git rev-parse --short HEAD) &&
502         echo "From $pwd/." >expect.err.2 &&
503         echo "   $head1..$head2  super      -> origin/super" >>expect.err.2 &&
504         head -3 expect.err >>expect.err.2 &&
505         (
506                 cd downstream &&
507                 rm .gitmodules &&
508                 git config fetch.recurseSubmodules on-demand &&
509                 # fake submodule configuration to avoid skipping submodule handling
510                 git config -f .gitmodules submodule.fake.path fake &&
511                 git config -f .gitmodules submodule.fake.url fakeurl &&
512                 git add .gitmodules &&
513                 git config --unset submodule.submodule.url &&
514                 git fetch >../actual.out 2>../actual.err &&
515                 # cleanup
516                 git config --unset fetch.recurseSubmodules &&
517                 git reset --hard
518         ) &&
519         test_must_be_empty actual.out &&
520         test_i18ncmp expect.err.2 actual.err &&
521         git checkout HEAD^ -- .gitmodules &&
522         git add .gitmodules &&
523         git commit -m "new submodule restored .gitmodules"
524 '
525
526 test_expect_success 'fetching submodules respects parallel settings' '
527         git config fetch.recurseSubmodules true &&
528         (
529                 cd downstream &&
530                 GIT_TRACE=$(pwd)/trace.out git fetch &&
531                 grep "1 tasks" trace.out &&
532                 GIT_TRACE=$(pwd)/trace.out git fetch --jobs 7 &&
533                 grep "7 tasks" trace.out &&
534                 git config submodule.fetchJobs 8 &&
535                 GIT_TRACE=$(pwd)/trace.out git fetch &&
536                 grep "8 tasks" trace.out &&
537                 GIT_TRACE=$(pwd)/trace.out git fetch --jobs 9 &&
538                 grep "9 tasks" trace.out
539         )
540 '
541
542 test_expect_success 'fetching submodule into a broken repository' '
543         # Prepare src and src/sub nested in it
544         git init src &&
545         (
546                 cd src &&
547                 git init sub &&
548                 git -C sub commit --allow-empty -m "initial in sub" &&
549                 git submodule add -- ./sub sub &&
550                 git commit -m "initial in top"
551         ) &&
552
553         # Clone the old-fashoned way
554         git clone src dst &&
555         git -C dst clone ../src/sub sub &&
556
557         # Make sure that old-fashoned layout is still supported
558         git -C dst status &&
559
560         # "diff" would find no change
561         git -C dst diff --exit-code &&
562
563         # Recursive-fetch works fine
564         git -C dst fetch --recurse-submodules &&
565
566         # Break the receiving submodule
567         rm -f dst/sub/.git/HEAD &&
568
569         # NOTE: without the fix the following tests will recurse forever!
570         # They should terminate with an error.
571
572         test_must_fail git -C dst status &&
573         test_must_fail git -C dst diff &&
574         test_must_fail git -C dst fetch --recurse-submodules
575 '
576
577 test_expect_success "fetch new commits when submodule got renamed" '
578         git clone . downstream_rename &&
579         (
580                 cd downstream_rename &&
581                 git submodule update --init --recursive &&
582                 git checkout -b rename &&
583                 git mv submodule submodule_renamed &&
584                 (
585                         cd submodule_renamed &&
586                         git checkout -b rename_sub &&
587                         echo a >a &&
588                         git add a &&
589                         git commit -ma &&
590                         git push origin rename_sub &&
591                         git rev-parse HEAD >../../expect
592                 ) &&
593                 git add submodule_renamed &&
594                 git commit -m "update renamed submodule" &&
595                 git push origin rename
596         ) &&
597         (
598                 cd downstream &&
599                 git fetch --recurse-submodules=on-demand &&
600                 (
601                         cd submodule &&
602                         git rev-parse origin/rename_sub >../../actual
603                 )
604         ) &&
605         test_cmp expect actual
606 '
607
608 test_expect_success "fetch new submodule commits on-demand outside standard refspec" '
609         # add a second submodule and ensure it is around in downstream first
610         git clone submodule sub1 &&
611         git submodule add ./sub1 &&
612         git commit -m "adding a second submodule" &&
613         git -C downstream pull &&
614         git -C downstream submodule update --init --recursive &&
615
616         git checkout --detach &&
617
618         C=$(git -C submodule commit-tree -m "new change outside refs/heads" HEAD^{tree}) &&
619         git -C submodule update-ref refs/changes/1 $C &&
620         git update-index --cacheinfo 160000 $C submodule &&
621         test_tick &&
622
623         D=$(git -C sub1 commit-tree -m "new change outside refs/heads" HEAD^{tree}) &&
624         git -C sub1 update-ref refs/changes/2 $D &&
625         git update-index --cacheinfo 160000 $D sub1 &&
626
627         git commit -m "updated submodules outside of refs/heads" &&
628         E=$(git rev-parse HEAD) &&
629         git update-ref refs/changes/3 $E &&
630         (
631                 cd downstream &&
632                 git fetch --recurse-submodules origin refs/changes/3:refs/heads/my_branch &&
633                 git -C submodule cat-file -t $C &&
634                 git -C sub1 cat-file -t $D &&
635                 git checkout --recurse-submodules FETCH_HEAD
636         )
637 '
638
639 test_expect_success 'fetch new submodule commit on-demand in FETCH_HEAD' '
640         # depends on the previous test for setup
641
642         C=$(git -C submodule commit-tree -m "another change outside refs/heads" HEAD^{tree}) &&
643         git -C submodule update-ref refs/changes/4 $C &&
644         git update-index --cacheinfo 160000 $C submodule &&
645         test_tick &&
646
647         D=$(git -C sub1 commit-tree -m "another change outside refs/heads" HEAD^{tree}) &&
648         git -C sub1 update-ref refs/changes/5 $D &&
649         git update-index --cacheinfo 160000 $D sub1 &&
650
651         git commit -m "updated submodules outside of refs/heads" &&
652         E=$(git rev-parse HEAD) &&
653         git update-ref refs/changes/6 $E &&
654         (
655                 cd downstream &&
656                 git fetch --recurse-submodules origin refs/changes/6 &&
657                 git -C submodule cat-file -t $C &&
658                 git -C sub1 cat-file -t $D &&
659                 git checkout --recurse-submodules FETCH_HEAD
660         )
661 '
662
663 test_expect_success 'fetch new submodule commits on-demand without .gitmodules entry' '
664         # depends on the previous test for setup
665
666         git config -f .gitmodules --remove-section submodule.sub1 &&
667         git add .gitmodules &&
668         git commit -m "delete gitmodules file" &&
669         git checkout -B super &&
670         git -C downstream fetch &&
671         git -C downstream checkout origin/super &&
672
673         C=$(git -C submodule commit-tree -m "yet another change outside refs/heads" HEAD^{tree}) &&
674         git -C submodule update-ref refs/changes/7 $C &&
675         git update-index --cacheinfo 160000 $C submodule &&
676         test_tick &&
677
678         D=$(git -C sub1 commit-tree -m "yet another change outside refs/heads" HEAD^{tree}) &&
679         git -C sub1 update-ref refs/changes/8 $D &&
680         git update-index --cacheinfo 160000 $D sub1 &&
681
682         git commit -m "updated submodules outside of refs/heads" &&
683         E=$(git rev-parse HEAD) &&
684         git update-ref refs/changes/9 $E &&
685         (
686                 cd downstream &&
687                 git fetch --recurse-submodules origin refs/changes/9 &&
688                 git -C submodule cat-file -t $C &&
689                 git -C sub1 cat-file -t $D &&
690                 git checkout --recurse-submodules FETCH_HEAD
691         )
692 '
693
694 test_expect_success 'fetch new submodule commit intermittently referenced by superproject' '
695         # depends on the previous test for setup
696
697         D=$(git -C sub1 commit-tree -m "change 10 outside refs/heads" HEAD^{tree}) &&
698         E=$(git -C sub1 commit-tree -m "change 11 outside refs/heads" HEAD^{tree}) &&
699         F=$(git -C sub1 commit-tree -m "change 12 outside refs/heads" HEAD^{tree}) &&
700
701         git -C sub1 update-ref refs/changes/10 $D &&
702         git update-index --cacheinfo 160000 $D sub1 &&
703         git commit -m "updated submodules outside of refs/heads" &&
704
705         git -C sub1 update-ref refs/changes/11 $E &&
706         git update-index --cacheinfo 160000 $E sub1 &&
707         git commit -m "updated submodules outside of refs/heads" &&
708
709         git -C sub1 update-ref refs/changes/12 $F &&
710         git update-index --cacheinfo 160000 $F sub1 &&
711         git commit -m "updated submodules outside of refs/heads" &&
712
713         G=$(git rev-parse HEAD) &&
714         git update-ref refs/changes/13 $G &&
715         (
716                 cd downstream &&
717                 git fetch --recurse-submodules origin refs/changes/13 &&
718
719                 git -C sub1 cat-file -t $D &&
720                 git -C sub1 cat-file -t $E &&
721                 git -C sub1 cat-file -t $F
722         )
723 '
724
725 add_commit_push () {
726         dir="$1" &&
727         msg="$2" &&
728         shift 2 &&
729         git -C "$dir" add "$@" &&
730         git -C "$dir" commit -a -m "$msg" &&
731         git -C "$dir" push
732 }
733
734 compare_refs_in_dir () {
735         fail= &&
736         if test "x$1" = 'x!'
737         then
738                 fail='!' &&
739                 shift
740         fi &&
741         git -C "$1" rev-parse --verify "$2" >expect &&
742         git -C "$3" rev-parse --verify "$4" >actual &&
743         eval $fail test_cmp expect actual
744 }
745
746
747 test_expect_success 'setup nested submodule fetch test' '
748         # does not depend on any previous test setups
749
750         for repo in outer middle inner
751         do
752                 git init --bare $repo &&
753                 git clone $repo ${repo}_content &&
754                 echo "$repo" >"${repo}_content/file" &&
755                 add_commit_push ${repo}_content "initial" file ||
756                 return 1
757         done &&
758
759         git clone outer A &&
760         git -C A submodule add "$pwd/middle" &&
761         git -C A/middle/ submodule add "$pwd/inner" &&
762         add_commit_push A/middle/ "adding inner sub" .gitmodules inner &&
763         add_commit_push A/ "adding middle sub" .gitmodules middle &&
764
765         git clone outer B &&
766         git -C B/ submodule update --init middle &&
767
768         compare_refs_in_dir A HEAD B HEAD &&
769         compare_refs_in_dir A/middle HEAD B/middle HEAD &&
770         test_path_is_file B/file &&
771         test_path_is_file B/middle/file &&
772         test_path_is_missing B/middle/inner/file &&
773
774         echo "change on inner repo of A" >"A/middle/inner/file" &&
775         add_commit_push A/middle/inner "change on inner" file &&
776         add_commit_push A/middle "change on inner" inner &&
777         add_commit_push A "change on inner" middle
778 '
779
780 test_expect_success 'fetching a superproject containing an uninitialized sub/sub project' '
781         # depends on previous test for setup
782
783         git -C B/ fetch &&
784         compare_refs_in_dir A origin/HEAD B origin/HEAD
785 '
786
787 fetch_with_recursion_abort () {
788         # In a regression the following git call will run into infinite recursion.
789         # To handle that, we connect the sed command to the git call by a pipe
790         # so that sed can kill the infinite recursion when detected.
791         # The recursion creates git output like:
792         # Fetching submodule sub
793         # Fetching submodule sub/sub              <-- [1]
794         # Fetching submodule sub/sub/sub
795         # ...
796         # [1] sed will stop reading and cause git to eventually stop and die
797
798         git -C "$1" fetch --recurse-submodules 2>&1 |
799                 sed "/Fetching submodule $2[^$]/q" >out &&
800         ! grep "Fetching submodule $2[^$]" out
801 }
802
803 test_expect_success 'setup recursive fetch with uninit submodule' '
804         # does not depend on any previous test setups
805
806         test_create_repo super &&
807         test_commit -C super initial &&
808         test_create_repo sub &&
809         test_commit -C sub initial &&
810         git -C sub rev-parse HEAD >expect &&
811
812         git -C super submodule add ../sub &&
813         git -C super commit -m "add sub" &&
814
815         git clone super superclone &&
816         git -C superclone submodule status >out &&
817         sed -e "s/^-//" -e "s/ sub.*$//" out >actual &&
818         test_cmp expect actual
819 '
820
821 test_expect_success 'recursive fetch with uninit submodule' '
822         # depends on previous test for setup
823
824         fetch_with_recursion_abort superclone sub &&
825         git -C superclone submodule status >out &&
826         sed -e "s/^-//" -e "s/ sub$//" out >actual &&
827         test_cmp expect actual
828 '
829
830 test_expect_success 'recursive fetch after deinit a submodule' '
831         # depends on previous test for setup
832
833         git -C superclone submodule update --init sub &&
834         git -C superclone submodule deinit -f sub &&
835
836         fetch_with_recursion_abort superclone sub &&
837         git -C superclone submodule status >out &&
838         sed -e "s/^-//" -e "s/ sub$//" out >actual &&
839         test_cmp expect actual
840 '
841
842 test_done