avoid segfault on submodule.*.path set to an empty "true"
[alt-git.git] / t / t7400-submodule-basic.sh
blob0edf74c68f6907aedc8c863d573138c31e7110f2
1 #!/bin/sh
3 # Copyright (c) 2007 Lars Hjemli
6 test_description='Basic porcelain support for submodules
8 This test tries to verify basic sanity of the init, update and status
9 subcommands of git submodule.
12 . ./test-lib.sh
14 test_expect_success 'setup - initial commit' '
15 >t &&
16 git add t &&
17 git commit -m "initial commit" &&
18 git branch initial
21 test_expect_success 'configuration parsing' '
22 test_when_finished "rm -f .gitmodules" &&
23 cat >.gitmodules <<-\EOF &&
24 [submodule "s"]
25 path
26 ignore
27 EOF
28 test_must_fail git status
31 test_expect_success 'setup - repository in init subdirectory' '
32 mkdir init &&
34 cd init &&
35 git init &&
36 echo a >a &&
37 git add a &&
38 git commit -m "submodule commit 1" &&
39 git tag -a -m "rev-1" rev-1
43 test_expect_success 'setup - commit with gitlink' '
44 echo a >a &&
45 echo z >z &&
46 git add a init z &&
47 git commit -m "super commit 1"
50 test_expect_success 'setup - hide init subdirectory' '
51 mv init .subrepo
54 test_expect_success 'setup - repository to add submodules to' '
55 git init addtest &&
56 git init addtest-ignore
59 # The 'submodule add' tests need some repository to add as a submodule.
60 # The trash directory is a good one as any. We need to canonicalize
61 # the name, though, as some tests compare it to the absolute path git
62 # generates, which will expand symbolic links.
63 submodurl=$(pwd -P)
65 listbranches() {
66 git for-each-ref --format='%(refname)' 'refs/heads/*'
69 inspect() {
70 dir=$1 &&
71 dotdot="${2:-..}" &&
74 cd "$dir" &&
75 listbranches >"$dotdot/heads" &&
76 { git symbolic-ref HEAD || :; } >"$dotdot/head" &&
77 git rev-parse HEAD >"$dotdot/head-sha1" &&
78 git update-index --refresh &&
79 git diff-files --exit-code &&
80 git clean -n -d -x >"$dotdot/untracked"
84 test_expect_success 'submodule add' '
85 echo "refs/heads/master" >expect &&
86 >empty &&
89 cd addtest &&
90 git submodule add -q "$submodurl" submod >actual &&
91 test ! -s actual &&
92 echo "gitdir: ../.git/modules/submod" >expect &&
93 test_cmp expect submod/.git &&
95 cd submod &&
96 git config core.worktree >actual &&
97 echo "../../../submod" >expect &&
98 test_cmp expect actual &&
99 rm -f actual expect
100 ) &&
101 git submodule init
102 ) &&
104 rm -f heads head untracked &&
105 inspect addtest/submod ../.. &&
106 test_cmp expect heads &&
107 test_cmp expect head &&
108 test_cmp empty untracked
111 test_expect_success 'submodule add to .gitignored path fails' '
113 cd addtest-ignore &&
114 cat <<-\EOF >expect &&
115 The following path is ignored by one of your .gitignore files:
116 submod
117 Use -f if you really want to add it.
119 # Does not use test_commit due to the ignore
120 echo "*" > .gitignore &&
121 git add --force .gitignore &&
122 git commit -m"Ignore everything" &&
123 ! git submodule add "$submodurl" submod >actual 2>&1 &&
124 test_i18ncmp expect actual
128 test_expect_success 'submodule add to .gitignored path with --force' '
130 cd addtest-ignore &&
131 git submodule add --force "$submodurl" submod
135 test_expect_success 'submodule add --branch' '
136 echo "refs/heads/initial" >expect-head &&
137 cat <<-\EOF >expect-heads &&
138 refs/heads/initial
139 refs/heads/master
141 >empty &&
144 cd addtest &&
145 git submodule add -b initial "$submodurl" submod-branch &&
146 test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
147 git submodule init
148 ) &&
150 rm -f heads head untracked &&
151 inspect addtest/submod-branch ../.. &&
152 test_cmp expect-heads heads &&
153 test_cmp expect-head head &&
154 test_cmp empty untracked
157 test_expect_success 'submodule add with ./ in path' '
158 echo "refs/heads/master" >expect &&
159 >empty &&
162 cd addtest &&
163 git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
164 git submodule init
165 ) &&
167 rm -f heads head untracked &&
168 inspect addtest/dotsubmod/frotz ../../.. &&
169 test_cmp expect heads &&
170 test_cmp expect head &&
171 test_cmp empty untracked
174 test_expect_success 'submodule add with // in path' '
175 echo "refs/heads/master" >expect &&
176 >empty &&
179 cd addtest &&
180 git submodule add "$submodurl" slashslashsubmod///frotz// &&
181 git submodule init
182 ) &&
184 rm -f heads head untracked &&
185 inspect addtest/slashslashsubmod/frotz ../../.. &&
186 test_cmp expect heads &&
187 test_cmp expect head &&
188 test_cmp empty untracked
191 test_expect_success 'submodule add with /.. in path' '
192 echo "refs/heads/master" >expect &&
193 >empty &&
196 cd addtest &&
197 git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
198 git submodule init
199 ) &&
201 rm -f heads head untracked &&
202 inspect addtest/realsubmod ../.. &&
203 test_cmp expect heads &&
204 test_cmp expect head &&
205 test_cmp empty untracked
208 test_expect_success 'submodule add with ./, /.. and // in path' '
209 echo "refs/heads/master" >expect &&
210 >empty &&
213 cd addtest &&
214 git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
215 git submodule init
216 ) &&
218 rm -f heads head untracked &&
219 inspect addtest/realsubmod2 ../.. &&
220 test_cmp expect heads &&
221 test_cmp expect head &&
222 test_cmp empty untracked
225 test_expect_success 'setup - add an example entry to .gitmodules' '
226 GIT_CONFIG=.gitmodules \
227 git config submodule.example.url git://example.com/init.git
230 test_expect_success 'status should fail for unmapped paths' '
231 test_must_fail git submodule status
234 test_expect_success 'setup - map path in .gitmodules' '
235 cat <<\EOF >expect &&
236 [submodule "example"]
237 url = git://example.com/init.git
238 path = init
241 GIT_CONFIG=.gitmodules git config submodule.example.path init &&
243 test_cmp expect .gitmodules
246 test_expect_success 'status should only print one line' '
247 git submodule status >lines &&
248 test_line_count = 1 lines
251 test_expect_success 'setup - fetch commit name from submodule' '
252 rev1=$(cd .subrepo && git rev-parse HEAD) &&
253 printf "rev1: %s\n" "$rev1" &&
254 test -n "$rev1"
257 test_expect_success 'status should initially be "missing"' '
258 git submodule status >lines &&
259 grep "^-$rev1" lines
262 test_expect_success 'init should register submodule url in .git/config' '
263 echo git://example.com/init.git >expect &&
265 git submodule init &&
266 git config submodule.example.url >url &&
267 git config submodule.example.url ./.subrepo &&
269 test_cmp expect url
272 test_failure_with_unknown_submodule () {
273 test_must_fail git submodule $1 no-such-submodule 2>output.err &&
274 grep "^error: .*no-such-submodule" output.err
277 test_expect_success 'init should fail with unknown submodule' '
278 test_failure_with_unknown_submodule init
281 test_expect_success 'update should fail with unknown submodule' '
282 test_failure_with_unknown_submodule update
285 test_expect_success 'status should fail with unknown submodule' '
286 test_failure_with_unknown_submodule status
289 test_expect_success 'sync should fail with unknown submodule' '
290 test_failure_with_unknown_submodule sync
293 test_expect_success 'update should fail when path is used by a file' '
294 echo hello >expect &&
296 echo "hello" >init &&
297 test_must_fail git submodule update &&
299 test_cmp expect init
302 test_expect_success 'update should fail when path is used by a nonempty directory' '
303 echo hello >expect &&
305 rm -fr init &&
306 mkdir init &&
307 echo "hello" >init/a &&
309 test_must_fail git submodule update &&
311 test_cmp expect init/a
314 test_expect_success 'update should work when path is an empty dir' '
315 rm -fr init &&
316 rm -f head-sha1 &&
317 echo "$rev1" >expect &&
319 mkdir init &&
320 git submodule update -q >update.out &&
321 test ! -s update.out &&
323 inspect init &&
324 test_cmp expect head-sha1
327 test_expect_success 'status should be "up-to-date" after update' '
328 git submodule status >list &&
329 grep "^ $rev1" list
332 test_expect_success 'status should be "modified" after submodule commit' '
334 cd init &&
335 echo b >b &&
336 git add b &&
337 git commit -m "submodule commit 2"
338 ) &&
340 rev2=$(cd init && git rev-parse HEAD) &&
341 test -n "$rev2" &&
342 git submodule status >list &&
344 grep "^+$rev2" list
347 test_expect_success 'the --cached sha1 should be rev1' '
348 git submodule --cached status >list &&
349 grep "^+$rev1" list
352 test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
353 git diff >diff &&
354 grep "^+Subproject commit $rev2" diff
357 test_expect_success 'update should checkout rev1' '
358 rm -f head-sha1 &&
359 echo "$rev1" >expect &&
361 git submodule update init &&
362 inspect init &&
364 test_cmp expect head-sha1
367 test_expect_success 'status should be "up-to-date" after update' '
368 git submodule status >list &&
369 grep "^ $rev1" list
372 test_expect_success 'checkout superproject with subproject already present' '
373 git checkout initial &&
374 git checkout master
377 test_expect_success 'apply submodule diff' '
378 >empty &&
380 git branch second &&
382 cd init &&
383 echo s >s &&
384 git add s &&
385 git commit -m "change subproject"
386 ) &&
387 git update-index --add init &&
388 git commit -m "change init" &&
389 git format-patch -1 --stdout >P.diff &&
390 git checkout second &&
391 git apply --index P.diff &&
393 git diff --cached master >staged &&
394 test_cmp empty staged
397 test_expect_success 'update --init' '
398 mv init init2 &&
399 git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
400 git config --remove-section submodule.example &&
401 test_must_fail git config submodule.example.url &&
403 git submodule update init > update.out &&
404 cat update.out &&
405 test_i18ngrep "not initialized" update.out &&
406 test_must_fail git rev-parse --resolve-git-dir init/.git &&
408 git submodule update --init init &&
409 git rev-parse --resolve-git-dir init/.git
412 test_expect_success 'do not add files from a submodule' '
414 git reset --hard &&
415 test_must_fail git add init/a
419 test_expect_success 'gracefully add submodule with a trailing slash' '
421 git reset --hard &&
422 git commit -m "commit subproject" init &&
423 (cd init &&
424 echo b > a) &&
425 git add init/ &&
426 git diff --exit-code --cached init &&
427 commit=$(cd init &&
428 git commit -m update a >/dev/null &&
429 git rev-parse HEAD) &&
430 git add init/ &&
431 test_must_fail git diff --exit-code --cached init &&
432 test $commit = $(git ls-files --stage |
433 sed -n "s/^160000 \([^ ]*\).*/\1/p")
437 test_expect_success 'ls-files gracefully handles trailing slash' '
439 test "init" = "$(git ls-files init/)"
443 test_expect_success 'moving to a commit without submodule does not leave empty dir' '
444 rm -rf init &&
445 mkdir init &&
446 git reset --hard &&
447 git checkout initial &&
448 test ! -d init &&
449 git checkout second
452 test_expect_success 'submodule <invalid-subcommand> fails' '
453 test_must_fail git submodule no-such-subcommand
456 test_expect_success 'add submodules without specifying an explicit path' '
457 mkdir repo &&
459 cd repo &&
460 git init &&
461 echo r >r &&
462 git add r &&
463 git commit -m "repo commit 1"
464 ) &&
465 git clone --bare repo/ bare.git &&
467 cd addtest &&
468 git submodule add "$submodurl/repo" &&
469 git config -f .gitmodules submodule.repo.path repo &&
470 git submodule add "$submodurl/bare.git" &&
471 git config -f .gitmodules submodule.bare.path bare
475 test_expect_success 'add should fail when path is used by a file' '
477 cd addtest &&
478 touch file &&
479 test_must_fail git submodule add "$submodurl/repo" file
483 test_expect_success 'add should fail when path is used by an existing directory' '
485 cd addtest &&
486 mkdir empty-dir &&
487 test_must_fail git submodule add "$submodurl/repo" empty-dir
491 test_expect_success 'use superproject as upstream when path is relative and no url is set there' '
493 cd addtest &&
494 git submodule add ../repo relative &&
495 test "$(git config -f .gitmodules submodule.relative.url)" = ../repo &&
496 git submodule sync relative &&
497 test "$(git config submodule.relative.url)" = "$submodurl/repo"
501 test_expect_success 'set up for relative path tests' '
502 mkdir reltest &&
504 cd reltest &&
505 git init &&
506 mkdir sub &&
508 cd sub &&
509 git init &&
510 test_commit foo
511 ) &&
512 git add sub &&
513 git config -f .gitmodules submodule.sub.path sub &&
514 git config -f .gitmodules submodule.sub.url ../subrepo &&
515 cp .git/config pristine-.git-config &&
516 cp .gitmodules pristine-.gitmodules
520 test_expect_success '../subrepo works with URL - ssh://hostname/repo' '
522 cd reltest &&
523 cp pristine-.git-config .git/config &&
524 cp pristine-.gitmodules .gitmodules &&
525 git config remote.origin.url ssh://hostname/repo &&
526 git submodule init &&
527 test "$(git config submodule.sub.url)" = ssh://hostname/subrepo
531 test_expect_success '../subrepo works with port-qualified URL - ssh://hostname:22/repo' '
533 cd reltest &&
534 cp pristine-.git-config .git/config &&
535 cp pristine-.gitmodules .gitmodules &&
536 git config remote.origin.url ssh://hostname:22/repo &&
537 git submodule init &&
538 test "$(git config submodule.sub.url)" = ssh://hostname:22/subrepo
542 # About the choice of the path in the next test:
543 # - double-slash side-steps path mangling issues on Windows
544 # - it is still an absolute local path
545 # - there cannot be a server with a blank in its name just in case the
546 # path is used erroneously to access a //server/share style path
547 test_expect_success '../subrepo path works with local path - //somewhere else/repo' '
549 cd reltest &&
550 cp pristine-.git-config .git/config &&
551 cp pristine-.gitmodules .gitmodules &&
552 git config remote.origin.url "//somewhere else/repo" &&
553 git submodule init &&
554 test "$(git config submodule.sub.url)" = "//somewhere else/subrepo"
558 test_expect_success '../subrepo works with file URL - file:///tmp/repo' '
560 cd reltest &&
561 cp pristine-.git-config .git/config &&
562 cp pristine-.gitmodules .gitmodules &&
563 git config remote.origin.url file:///tmp/repo &&
564 git submodule init &&
565 test "$(git config submodule.sub.url)" = file:///tmp/subrepo
569 test_expect_success '../subrepo works with helper URL- helper:://hostname/repo' '
571 cd reltest &&
572 cp pristine-.git-config .git/config &&
573 cp pristine-.gitmodules .gitmodules &&
574 git config remote.origin.url helper:://hostname/repo &&
575 git submodule init &&
576 test "$(git config submodule.sub.url)" = helper:://hostname/subrepo
580 test_expect_success '../subrepo works with scp-style URL - user@host:repo' '
582 cd reltest &&
583 cp pristine-.git-config .git/config &&
584 git config remote.origin.url user@host:repo &&
585 git submodule init &&
586 test "$(git config submodule.sub.url)" = user@host:subrepo
590 test_expect_success '../subrepo works with scp-style URL - user@host:path/to/repo' '
592 cd reltest &&
593 cp pristine-.git-config .git/config &&
594 cp pristine-.gitmodules .gitmodules &&
595 git config remote.origin.url user@host:path/to/repo &&
596 git submodule init &&
597 test "$(git config submodule.sub.url)" = user@host:path/to/subrepo
601 test_expect_success '../subrepo works with relative local path - foo' '
603 cd reltest &&
604 cp pristine-.git-config .git/config &&
605 cp pristine-.gitmodules .gitmodules &&
606 git config remote.origin.url foo &&
607 # actual: fails with an error
608 git submodule init &&
609 test "$(git config submodule.sub.url)" = subrepo
613 test_expect_success '../subrepo works with relative local path - foo/bar' '
615 cd reltest &&
616 cp pristine-.git-config .git/config &&
617 cp pristine-.gitmodules .gitmodules &&
618 git config remote.origin.url foo/bar &&
619 git submodule init &&
620 test "$(git config submodule.sub.url)" = foo/subrepo
624 test_expect_success '../subrepo works with relative local path - ./foo' '
626 cd reltest &&
627 cp pristine-.git-config .git/config &&
628 cp pristine-.gitmodules .gitmodules &&
629 git config remote.origin.url ./foo &&
630 git submodule init &&
631 test "$(git config submodule.sub.url)" = subrepo
635 test_expect_success '../subrepo works with relative local path - ./foo/bar' '
637 cd reltest &&
638 cp pristine-.git-config .git/config &&
639 cp pristine-.gitmodules .gitmodules &&
640 git config remote.origin.url ./foo/bar &&
641 git submodule init &&
642 test "$(git config submodule.sub.url)" = foo/subrepo
646 test_expect_success '../subrepo works with relative local path - ../foo' '
648 cd reltest &&
649 cp pristine-.git-config .git/config &&
650 cp pristine-.gitmodules .gitmodules &&
651 git config remote.origin.url ../foo &&
652 git submodule init &&
653 test "$(git config submodule.sub.url)" = ../subrepo
657 test_expect_success '../subrepo works with relative local path - ../foo/bar' '
659 cd reltest &&
660 cp pristine-.git-config .git/config &&
661 cp pristine-.gitmodules .gitmodules &&
662 git config remote.origin.url ../foo/bar &&
663 git submodule init &&
664 test "$(git config submodule.sub.url)" = ../foo/subrepo
668 test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.git' '
670 cd reltest &&
671 cp pristine-.git-config .git/config &&
672 cp pristine-.gitmodules .gitmodules &&
673 mkdir -p a/b/c &&
674 (cd a/b/c; git init) &&
675 git config remote.origin.url ../foo/bar.git &&
676 git submodule add ../bar/a/b/c ./a/b/c &&
677 git submodule init &&
678 test "$(git config submodule.a/b/c.url)" = ../foo/bar/a/b/c
682 test_expect_success 'moving the superproject does not break submodules' '
684 cd addtest &&
685 git submodule status >expect
687 mv addtest addtest2 &&
689 cd addtest2 &&
690 git submodule status >actual &&
691 test_cmp expect actual
695 test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' '
697 cd addtest2 &&
699 cd repo &&
700 echo "$submodurl/repo" >expect &&
701 git config remote.origin.url >actual &&
702 test_cmp expect actual &&
703 echo "gitdir: ../.git/modules/repo" >expect &&
704 test_cmp expect .git
705 ) &&
706 rm -rf repo &&
707 git rm repo &&
708 git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
709 test ! -s actual &&
710 echo "gitdir: ../.git/modules/submod" >expect &&
711 test_cmp expect submod/.git &&
713 cd repo &&
714 echo "$submodurl/bare.git" >expect &&
715 git config remote.origin.url >actual &&
716 test_cmp expect actual &&
717 echo "gitdir: ../.git/modules/repo_new" >expect &&
718 test_cmp expect .git
719 ) &&
720 echo "repo" >expect &&
721 git config -f .gitmodules submodule.repo.path >actual &&
722 test_cmp expect actual &&
723 git config -f .gitmodules submodule.repo_new.path >actual &&
724 test_cmp expect actual&&
725 echo "$submodurl/repo" >expect &&
726 git config -f .gitmodules submodule.repo.url >actual &&
727 test_cmp expect actual &&
728 echo "$submodurl/bare.git" >expect &&
729 git config -f .gitmodules submodule.repo_new.url >actual &&
730 test_cmp expect actual &&
731 echo "$submodurl/repo" >expect &&
732 git config submodule.repo.url >actual &&
733 test_cmp expect actual &&
734 echo "$submodurl/bare.git" >expect &&
735 git config submodule.repo_new.url >actual &&
736 test_cmp expect actual
740 test_expect_success 'submodule add with an existing name fails unless forced' '
742 cd addtest2 &&
743 rm -rf repo &&
744 git rm repo &&
745 test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" repo &&
746 test ! -d repo &&
747 echo "repo" >expect &&
748 git config -f .gitmodules submodule.repo_new.path >actual &&
749 test_cmp expect actual&&
750 echo "$submodurl/bare.git" >expect &&
751 git config -f .gitmodules submodule.repo_new.url >actual &&
752 test_cmp expect actual &&
753 echo "$submodurl/bare.git" >expect &&
754 git config submodule.repo_new.url >actual &&
755 test_cmp expect actual &&
756 git submodule add -f -q --name repo_new "$submodurl/repo.git" repo &&
757 test -d repo &&
758 echo "repo" >expect &&
759 git config -f .gitmodules submodule.repo_new.path >actual &&
760 test_cmp expect actual&&
761 echo "$submodurl/repo.git" >expect &&
762 git config -f .gitmodules submodule.repo_new.url >actual &&
763 test_cmp expect actual &&
764 echo "$submodurl/repo.git" >expect &&
765 git config submodule.repo_new.url >actual &&
766 test_cmp expect actual
770 test_done