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