Merge branch 'jc/mention-tracking-for-pull-default'
[git.git] / t / t7400-submodule-basic.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Lars Hjemli
4 #
5
6 test_description='Basic porcelain support for submodules
7
8 This test tries to verify basic sanity of the init, update and status
9 subcommands of git submodule.
10 '
11
12 . ./test-lib.sh
13
14 test_expect_success 'setup - initial commit' '
15         >t &&
16         git add t &&
17         git commit -m "initial commit" &&
18         git branch initial
19 '
20
21 test_expect_success 'setup - repository in init subdirectory' '
22         mkdir init &&
23         (
24                 cd init &&
25                 git init &&
26                 echo a >a &&
27                 git add a &&
28                 git commit -m "submodule commit 1" &&
29                 git tag -a -m "rev-1" rev-1
30         )
31 '
32
33 test_expect_success 'setup - commit with gitlink' '
34         echo a >a &&
35         echo z >z &&
36         git add a init z &&
37         git commit -m "super commit 1"
38 '
39
40 test_expect_success 'setup - hide init subdirectory' '
41         mv init .subrepo
42 '
43
44 test_expect_success 'setup - repository to add submodules to' '
45         git init addtest &&
46         git init addtest-ignore
47 '
48
49 # The 'submodule add' tests need some repository to add as a submodule.
50 # The trash directory is a good one as any. We need to canonicalize
51 # the name, though, as some tests compare it to the absolute path git
52 # generates, which will expand symbolic links.
53 submodurl=$(pwd -P)
54
55 listbranches() {
56         git for-each-ref --format='%(refname)' 'refs/heads/*'
57 }
58
59 inspect() {
60         dir=$1 &&
61         dotdot="${2:-..}" &&
62
63         (
64                 cd "$dir" &&
65                 listbranches >"$dotdot/heads" &&
66                 { git symbolic-ref HEAD || :; } >"$dotdot/head" &&
67                 git rev-parse HEAD >"$dotdot/head-sha1" &&
68                 git update-index --refresh &&
69                 git diff-files --exit-code &&
70                 git clean -n -d -x >"$dotdot/untracked"
71         )
72 }
73
74 test_expect_success 'submodule add' '
75         echo "refs/heads/master" >expect &&
76         >empty &&
77
78         (
79                 cd addtest &&
80                 git submodule add -q "$submodurl" submod >actual &&
81                 test ! -s actual &&
82                 echo "gitdir: ../.git/modules/submod" >expect &&
83                 test_cmp expect submod/.git &&
84                 (
85                         cd submod &&
86                         git config core.worktree >actual &&
87                         echo "../../../submod" >expect &&
88                         test_cmp expect actual &&
89                         rm -f actual expect
90                 ) &&
91                 git submodule init
92         ) &&
93
94         rm -f heads head untracked &&
95         inspect addtest/submod ../.. &&
96         test_cmp expect heads &&
97         test_cmp expect head &&
98         test_cmp empty untracked
99 '
100
101 test_expect_success 'submodule add to .gitignored path fails' '
102         (
103                 cd addtest-ignore &&
104                 cat <<-\EOF >expect &&
105                 The following path is ignored by one of your .gitignore files:
106                 submod
107                 Use -f if you really want to add it.
108                 EOF
109                 # Does not use test_commit due to the ignore
110                 echo "*" > .gitignore &&
111                 git add --force .gitignore &&
112                 git commit -m"Ignore everything" &&
113                 ! git submodule add "$submodurl" submod >actual 2>&1 &&
114                 test_i18ncmp expect actual
115         )
116 '
117
118 test_expect_success 'submodule add to .gitignored path with --force' '
119         (
120                 cd addtest-ignore &&
121                 git submodule add --force "$submodurl" submod
122         )
123 '
124
125 test_expect_success 'submodule add --branch' '
126         echo "refs/heads/initial" >expect-head &&
127         cat <<-\EOF >expect-heads &&
128         refs/heads/initial
129         refs/heads/master
130         EOF
131         >empty &&
132
133         (
134                 cd addtest &&
135                 git submodule add -b initial "$submodurl" submod-branch &&
136                 test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
137                 git submodule init
138         ) &&
139
140         rm -f heads head untracked &&
141         inspect addtest/submod-branch ../.. &&
142         test_cmp expect-heads heads &&
143         test_cmp expect-head head &&
144         test_cmp empty untracked
145 '
146
147 test_expect_success 'submodule add with ./ in path' '
148         echo "refs/heads/master" >expect &&
149         >empty &&
150
151         (
152                 cd addtest &&
153                 git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
154                 git submodule init
155         ) &&
156
157         rm -f heads head untracked &&
158         inspect addtest/dotsubmod/frotz ../../.. &&
159         test_cmp expect heads &&
160         test_cmp expect head &&
161         test_cmp empty untracked
162 '
163
164 test_expect_success 'submodule add with // in path' '
165         echo "refs/heads/master" >expect &&
166         >empty &&
167
168         (
169                 cd addtest &&
170                 git submodule add "$submodurl" slashslashsubmod///frotz// &&
171                 git submodule init
172         ) &&
173
174         rm -f heads head untracked &&
175         inspect addtest/slashslashsubmod/frotz ../../.. &&
176         test_cmp expect heads &&
177         test_cmp expect head &&
178         test_cmp empty untracked
179 '
180
181 test_expect_success 'submodule add with /.. in path' '
182         echo "refs/heads/master" >expect &&
183         >empty &&
184
185         (
186                 cd addtest &&
187                 git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
188                 git submodule init
189         ) &&
190
191         rm -f heads head untracked &&
192         inspect addtest/realsubmod ../.. &&
193         test_cmp expect heads &&
194         test_cmp expect head &&
195         test_cmp empty untracked
196 '
197
198 test_expect_success 'submodule add with ./, /.. and // in path' '
199         echo "refs/heads/master" >expect &&
200         >empty &&
201
202         (
203                 cd addtest &&
204                 git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
205                 git submodule init
206         ) &&
207
208         rm -f heads head untracked &&
209         inspect addtest/realsubmod2 ../.. &&
210         test_cmp expect heads &&
211         test_cmp expect head &&
212         test_cmp empty untracked
213 '
214
215 test_expect_success 'setup - add an example entry to .gitmodules' '
216         GIT_CONFIG=.gitmodules \
217         git config submodule.example.url git://example.com/init.git
218 '
219
220 test_expect_success 'status should fail for unmapped paths' '
221         test_must_fail git submodule status
222 '
223
224 test_expect_success 'setup - map path in .gitmodules' '
225         cat <<\EOF >expect &&
226 [submodule "example"]
227         url = git://example.com/init.git
228         path = init
229 EOF
230
231         GIT_CONFIG=.gitmodules git config submodule.example.path init &&
232
233         test_cmp expect .gitmodules
234 '
235
236 test_expect_success 'status should only print one line' '
237         git submodule status >lines &&
238         test_line_count = 1 lines
239 '
240
241 test_expect_success 'setup - fetch commit name from submodule' '
242         rev1=$(cd .subrepo && git rev-parse HEAD) &&
243         printf "rev1: %s\n" "$rev1" &&
244         test -n "$rev1"
245 '
246
247 test_expect_success 'status should initially be "missing"' '
248         git submodule status >lines &&
249         grep "^-$rev1" lines
250 '
251
252 test_expect_success 'init should register submodule url in .git/config' '
253         echo git://example.com/init.git >expect &&
254
255         git submodule init &&
256         git config submodule.example.url >url &&
257         git config submodule.example.url ./.subrepo &&
258
259         test_cmp expect url
260 '
261
262 test_failure_with_unknown_submodule () {
263         test_must_fail git submodule $1 no-such-submodule 2>output.err &&
264         grep "^error: .*no-such-submodule" output.err
265 }
266
267 test_expect_success 'init should fail with unknown submodule' '
268         test_failure_with_unknown_submodule init
269 '
270
271 test_expect_success 'update should fail with unknown submodule' '
272         test_failure_with_unknown_submodule update
273 '
274
275 test_expect_success 'status should fail with unknown submodule' '
276         test_failure_with_unknown_submodule status
277 '
278
279 test_expect_success 'sync should fail with unknown submodule' '
280         test_failure_with_unknown_submodule sync
281 '
282
283 test_expect_success 'update should fail when path is used by a file' '
284         echo hello >expect &&
285
286         echo "hello" >init &&
287         test_must_fail git submodule update &&
288
289         test_cmp expect init
290 '
291
292 test_expect_success 'update should fail when path is used by a nonempty directory' '
293         echo hello >expect &&
294
295         rm -fr init &&
296         mkdir init &&
297         echo "hello" >init/a &&
298
299         test_must_fail git submodule update &&
300
301         test_cmp expect init/a
302 '
303
304 test_expect_success 'update should work when path is an empty dir' '
305         rm -fr init &&
306         rm -f head-sha1 &&
307         echo "$rev1" >expect &&
308
309         mkdir init &&
310         git submodule update -q >update.out &&
311         test ! -s update.out &&
312
313         inspect init &&
314         test_cmp expect head-sha1
315 '
316
317 test_expect_success 'status should be "up-to-date" after update' '
318         git submodule status >list &&
319         grep "^ $rev1" list
320 '
321
322 test_expect_success 'status should be "modified" after submodule commit' '
323         (
324                 cd init &&
325                 echo b >b &&
326                 git add b &&
327                 git commit -m "submodule commit 2"
328         ) &&
329
330         rev2=$(cd init && git rev-parse HEAD) &&
331         test -n "$rev2" &&
332         git submodule status >list &&
333
334         grep "^+$rev2" list
335 '
336
337 test_expect_success 'the --cached sha1 should be rev1' '
338         git submodule --cached status >list &&
339         grep "^+$rev1" list
340 '
341
342 test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
343         git diff >diff &&
344         grep "^+Subproject commit $rev2" diff
345 '
346
347 test_expect_success 'update should checkout rev1' '
348         rm -f head-sha1 &&
349         echo "$rev1" >expect &&
350
351         git submodule update init &&
352         inspect init &&
353
354         test_cmp expect head-sha1
355 '
356
357 test_expect_success 'status should be "up-to-date" after update' '
358         git submodule status >list &&
359         grep "^ $rev1" list
360 '
361
362 test_expect_success 'checkout superproject with subproject already present' '
363         git checkout initial &&
364         git checkout master
365 '
366
367 test_expect_success 'apply submodule diff' '
368         >empty &&
369
370         git branch second &&
371         (
372                 cd init &&
373                 echo s >s &&
374                 git add s &&
375                 git commit -m "change subproject"
376         ) &&
377         git update-index --add init &&
378         git commit -m "change init" &&
379         git format-patch -1 --stdout >P.diff &&
380         git checkout second &&
381         git apply --index P.diff &&
382
383         git diff --cached master >staged &&
384         test_cmp empty staged
385 '
386
387 test_expect_success 'update --init' '
388         mv init init2 &&
389         git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
390         git config --remove-section submodule.example &&
391         test_must_fail git config submodule.example.url &&
392
393         git submodule update init > update.out &&
394         cat update.out &&
395         test_i18ngrep "not initialized" update.out &&
396         test_must_fail git rev-parse --resolve-git-dir init/.git &&
397
398         git submodule update --init init &&
399         git rev-parse --resolve-git-dir init/.git
400 '
401
402 test_expect_success 'do not add files from a submodule' '
403
404         git reset --hard &&
405         test_must_fail git add init/a
406
407 '
408
409 test_expect_success 'gracefully add submodule with a trailing slash' '
410
411         git reset --hard &&
412         git commit -m "commit subproject" init &&
413         (cd init &&
414          echo b > a) &&
415         git add init/ &&
416         git diff --exit-code --cached init &&
417         commit=$(cd init &&
418          git commit -m update a >/dev/null &&
419          git rev-parse HEAD) &&
420         git add init/ &&
421         test_must_fail git diff --exit-code --cached init &&
422         test $commit = $(git ls-files --stage |
423                 sed -n "s/^160000 \([^ ]*\).*/\1/p")
424
425 '
426
427 test_expect_success 'ls-files gracefully handles trailing slash' '
428
429         test "init" = "$(git ls-files init/)"
430
431 '
432
433 test_expect_success 'moving to a commit without submodule does not leave empty dir' '
434         rm -rf init &&
435         mkdir init &&
436         git reset --hard &&
437         git checkout initial &&
438         test ! -d init &&
439         git checkout second
440 '
441
442 test_expect_success 'submodule <invalid-subcommand> fails' '
443         test_must_fail git submodule no-such-subcommand
444 '
445
446 test_expect_success 'add submodules without specifying an explicit path' '
447         mkdir repo &&
448         (
449                 cd repo &&
450                 git init &&
451                 echo r >r &&
452                 git add r &&
453                 git commit -m "repo commit 1"
454         ) &&
455         git clone --bare repo/ bare.git &&
456         (
457                 cd addtest &&
458                 git submodule add "$submodurl/repo" &&
459                 git config -f .gitmodules submodule.repo.path repo &&
460                 git submodule add "$submodurl/bare.git" &&
461                 git config -f .gitmodules submodule.bare.path bare
462         )
463 '
464
465 test_expect_success 'add should fail when path is used by a file' '
466         (
467                 cd addtest &&
468                 touch file &&
469                 test_must_fail  git submodule add "$submodurl/repo" file
470         )
471 '
472
473 test_expect_success 'add should fail when path is used by an existing directory' '
474         (
475                 cd addtest &&
476                 mkdir empty-dir &&
477                 test_must_fail git submodule add "$submodurl/repo" empty-dir
478         )
479 '
480
481 test_expect_success 'use superproject as upstream when path is relative and no url is set there' '
482         (
483                 cd addtest &&
484                 git submodule add ../repo relative &&
485                 test "$(git config -f .gitmodules submodule.relative.url)" = ../repo &&
486                 git submodule sync relative &&
487                 test "$(git config submodule.relative.url)" = "$submodurl/repo"
488         )
489 '
490
491 test_expect_success 'set up for relative path tests' '
492         mkdir reltest &&
493         (
494                 cd reltest &&
495                 git init &&
496                 mkdir sub &&
497                 (
498                         cd sub &&
499                         git init &&
500                         test_commit foo
501                 ) &&
502                 git add sub &&
503                 git config -f .gitmodules submodule.sub.path sub &&
504                 git config -f .gitmodules submodule.sub.url ../subrepo &&
505                 cp .git/config pristine-.git-config &&
506                 cp .gitmodules pristine-.gitmodules
507         )
508 '
509
510 test_expect_success '../subrepo works with URL - ssh://hostname/repo' '
511         (
512                 cd reltest &&
513                 cp pristine-.git-config .git/config &&
514                 cp pristine-.gitmodules .gitmodules &&
515                 git config remote.origin.url ssh://hostname/repo &&
516                 git submodule init &&
517                 test "$(git config submodule.sub.url)" = ssh://hostname/subrepo
518         )
519 '
520
521 test_expect_success '../subrepo works with port-qualified URL - ssh://hostname:22/repo' '
522         (
523                 cd reltest &&
524                 cp pristine-.git-config .git/config &&
525                 cp pristine-.gitmodules .gitmodules &&
526                 git config remote.origin.url ssh://hostname:22/repo &&
527                 git submodule init &&
528                 test "$(git config submodule.sub.url)" = ssh://hostname:22/subrepo
529         )
530 '
531
532 # About the choice of the path in the next test:
533 # - double-slash side-steps path mangling issues on Windows
534 # - it is still an absolute local path
535 # - there cannot be a server with a blank in its name just in case the
536 #   path is used erroneously to access a //server/share style path
537 test_expect_success '../subrepo path works with local path - //somewhere else/repo' '
538         (
539                 cd reltest &&
540                 cp pristine-.git-config .git/config &&
541                 cp pristine-.gitmodules .gitmodules &&
542                 git config remote.origin.url "//somewhere else/repo" &&
543                 git submodule init &&
544                 test "$(git config submodule.sub.url)" = "//somewhere else/subrepo"
545         )
546 '
547
548 test_expect_success '../subrepo works with file URL - file:///tmp/repo' '
549         (
550                 cd reltest &&
551                 cp pristine-.git-config .git/config &&
552                 cp pristine-.gitmodules .gitmodules &&
553                 git config remote.origin.url file:///tmp/repo &&
554                 git submodule init &&
555                 test "$(git config submodule.sub.url)" = file:///tmp/subrepo
556         )
557 '
558
559 test_expect_success '../subrepo works with helper URL- helper:://hostname/repo' '
560         (
561                 cd reltest &&
562                 cp pristine-.git-config .git/config &&
563                 cp pristine-.gitmodules .gitmodules &&
564                 git config remote.origin.url helper:://hostname/repo &&
565                 git submodule init &&
566                 test "$(git config submodule.sub.url)" = helper:://hostname/subrepo
567         )
568 '
569
570 test_expect_success '../subrepo works with scp-style URL - user@host:repo' '
571         (
572                 cd reltest &&
573                 cp pristine-.git-config .git/config &&
574                 git config remote.origin.url user@host:repo &&
575                 git submodule init &&
576                 test "$(git config submodule.sub.url)" = user@host:subrepo
577         )
578 '
579
580 test_expect_success '../subrepo works with scp-style URL - user@host:path/to/repo' '
581         (
582                 cd reltest &&
583                 cp pristine-.git-config .git/config &&
584                 cp pristine-.gitmodules .gitmodules &&
585                 git config remote.origin.url user@host:path/to/repo &&
586                 git submodule init &&
587                 test "$(git config submodule.sub.url)" = user@host:path/to/subrepo
588         )
589 '
590
591 test_expect_success '../subrepo works with relative local path - foo' '
592         (
593                 cd reltest &&
594                 cp pristine-.git-config .git/config &&
595                 cp pristine-.gitmodules .gitmodules &&
596                 git config remote.origin.url foo &&
597                 # actual: fails with an error
598                 git submodule init &&
599                 test "$(git config submodule.sub.url)" = subrepo
600         )
601 '
602
603 test_expect_success '../subrepo works with relative local path - foo/bar' '
604         (
605                 cd reltest &&
606                 cp pristine-.git-config .git/config &&
607                 cp pristine-.gitmodules .gitmodules &&
608                 git config remote.origin.url foo/bar &&
609                 git submodule init &&
610                 test "$(git config submodule.sub.url)" = foo/subrepo
611         )
612 '
613
614 test_expect_success '../subrepo works with relative local path - ./foo' '
615         (
616                 cd reltest &&
617                 cp pristine-.git-config .git/config &&
618                 cp pristine-.gitmodules .gitmodules &&
619                 git config remote.origin.url ./foo &&
620                 git submodule init &&
621                 test "$(git config submodule.sub.url)" = subrepo
622         )
623 '
624
625 test_expect_success '../subrepo works with relative local path - ./foo/bar' '
626         (
627                 cd reltest &&
628                 cp pristine-.git-config .git/config &&
629                 cp pristine-.gitmodules .gitmodules &&
630                 git config remote.origin.url ./foo/bar &&
631                 git submodule init &&
632                 test "$(git config submodule.sub.url)" = foo/subrepo
633         )
634 '
635
636 test_expect_success '../subrepo works with relative local path - ../foo' '
637         (
638                 cd reltest &&
639                 cp pristine-.git-config .git/config &&
640                 cp pristine-.gitmodules .gitmodules &&
641                 git config remote.origin.url ../foo &&
642                 git submodule init &&
643                 test "$(git config submodule.sub.url)" = ../subrepo
644         )
645 '
646
647 test_expect_success '../subrepo works with relative local path - ../foo/bar' '
648         (
649                 cd reltest &&
650                 cp pristine-.git-config .git/config &&
651                 cp pristine-.gitmodules .gitmodules &&
652                 git config remote.origin.url ../foo/bar &&
653                 git submodule init &&
654                 test "$(git config submodule.sub.url)" = ../foo/subrepo
655         )
656 '
657
658 test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.git' '
659         (
660                 cd reltest &&
661                 cp pristine-.git-config .git/config &&
662                 cp pristine-.gitmodules .gitmodules &&
663                 mkdir -p a/b/c &&
664                 (cd a/b/c; git init) &&
665                 git config remote.origin.url ../foo/bar.git &&
666                 git submodule add ../bar/a/b/c ./a/b/c &&
667                 git submodule init &&
668                 test "$(git config submodule.a/b/c.url)" = ../foo/bar/a/b/c
669         )
670 '
671
672 test_expect_success 'moving the superproject does not break submodules' '
673         (
674                 cd addtest &&
675                 git submodule status >expect
676         )
677         mv addtest addtest2 &&
678         (
679                 cd addtest2 &&
680                 git submodule status >actual &&
681                 test_cmp expect actual
682         )
683 '
684
685 test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' '
686         (
687                 cd addtest2 &&
688                 (
689                         cd repo &&
690                         echo "$submodurl/repo" >expect &&
691                         git config remote.origin.url >actual &&
692                         test_cmp expect actual &&
693                         echo "gitdir: ../.git/modules/repo" >expect &&
694                         test_cmp expect .git
695                 ) &&
696                 rm -rf repo &&
697                 git rm repo &&
698                 git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
699                 test ! -s actual &&
700                 echo "gitdir: ../.git/modules/submod" >expect &&
701                 test_cmp expect submod/.git &&
702                 (
703                         cd repo &&
704                         echo "$submodurl/bare.git" >expect &&
705                         git config remote.origin.url >actual &&
706                         test_cmp expect actual &&
707                         echo "gitdir: ../.git/modules/repo_new" >expect &&
708                         test_cmp expect .git
709                 ) &&
710                 echo "repo" >expect &&
711                 git config -f .gitmodules submodule.repo.path >actual &&
712                 test_cmp expect actual &&
713                 git config -f .gitmodules submodule.repo_new.path >actual &&
714                 test_cmp expect actual&&
715                 echo "$submodurl/repo" >expect &&
716                 git config -f .gitmodules submodule.repo.url >actual &&
717                 test_cmp expect actual &&
718                 echo "$submodurl/bare.git" >expect &&
719                 git config -f .gitmodules submodule.repo_new.url >actual &&
720                 test_cmp expect actual &&
721                 echo "$submodurl/repo" >expect &&
722                 git config submodule.repo.url >actual &&
723                 test_cmp expect actual &&
724                 echo "$submodurl/bare.git" >expect &&
725                 git config submodule.repo_new.url >actual &&
726                 test_cmp expect actual
727         )
728 '
729
730 test_expect_success 'submodule add with an existing name fails unless forced' '
731         (
732                 cd addtest2 &&
733                 rm -rf repo &&
734                 git rm repo &&
735                 test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" repo &&
736                 test ! -d repo &&
737                 echo "repo" >expect &&
738                 git config -f .gitmodules submodule.repo_new.path >actual &&
739                 test_cmp expect actual&&
740                 echo "$submodurl/bare.git" >expect &&
741                 git config -f .gitmodules submodule.repo_new.url >actual &&
742                 test_cmp expect actual &&
743                 echo "$submodurl/bare.git" >expect &&
744                 git config submodule.repo_new.url >actual &&
745                 test_cmp expect actual &&
746                 git submodule add -f -q --name repo_new "$submodurl/repo.git" repo &&
747                 test -d repo &&
748                 echo "repo" >expect &&
749                 git config -f .gitmodules submodule.repo_new.path >actual &&
750                 test_cmp expect actual&&
751                 echo "$submodurl/repo.git" >expect &&
752                 git config -f .gitmodules submodule.repo_new.url >actual &&
753                 test_cmp expect actual &&
754                 echo "$submodurl/repo.git" >expect &&
755                 git config submodule.repo_new.url >actual &&
756                 test_cmp expect actual
757         )
758 '
759
760 test_done