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.
14 test_expect_success
'setup - initial commit' '
17 git commit -m "initial commit" &&
21 test_expect_success
'configuration parsing' '
22 test_when_finished "rm -f .gitmodules" &&
23 cat >.gitmodules <<-\EOF &&
28 test_must_fail git status
31 test_expect_success
'setup - repository in init subdirectory' '
38 git commit -m "submodule commit 1" &&
39 git tag -a -m "rev-1" rev-1
43 test_expect_success
'setup - commit with gitlink' '
47 git commit -m "super commit 1"
50 test_expect_success
'setup - hide init subdirectory' '
54 test_expect_success
'setup - repository to add submodules to' '
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.
66 git for-each-ref
--format='%(refname)' 'refs/heads/*'
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 &&
90 git submodule add -q "$submodurl" submod >actual &&
92 echo "gitdir: ../.git/modules/submod" >expect &&
93 test_cmp expect submod/.git &&
96 git config core.worktree >actual &&
97 echo "../../../submod" >expect &&
98 test_cmp expect actual &&
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' '
114 cat <<-\EOF >expect &&
115 The following path is ignored by one of your .gitignore files:
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' '
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 &&
145 git submodule add -b initial "$submodurl" submod-branch &&
146 test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
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 &&
163 git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
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 &&
180 git submodule add "$submodurl" slashslashsubmod///frotz// &&
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 &&
197 git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
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 &&
214 git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
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
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" &&
257 test_expect_success
'status should initially be "missing"' '
258 git submodule status >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 &&
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 &&
302 test_expect_success
'update should fail when path is used by a nonempty directory' '
303 echo hello >expect &&
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' '
317 echo "$rev1" >expect &&
320 git submodule update -q >update.out &&
321 test ! -s update.out &&
324 test_cmp expect head-sha1
327 test_expect_success
'status should be "up-to-date" after update' '
328 git submodule status >list &&
332 test_expect_success
'status should be "modified" after submodule commit' '
337 git commit -m "submodule commit 2"
340 rev2=$(cd init && git rev-parse HEAD) &&
342 git submodule status >list &&
347 test_expect_success
'the --cached sha1 should be rev1' '
348 git submodule --cached status >list &&
352 test_expect_success
'git diff should report the SHA1 of the new submodule commit' '
354 grep "^+Subproject commit $rev2" diff
357 test_expect_success
'update should checkout rev1' '
359 echo "$rev1" >expect &&
361 git submodule update init &&
364 test_cmp expect head-sha1
367 test_expect_success
'status should be "up-to-date" after update' '
368 git submodule status >list &&
372 test_expect_success
'checkout superproject with subproject already present' '
373 git checkout initial &&
377 test_expect_success
'apply submodule diff' '
385 git commit -m "change subproject"
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' '
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 &&
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' '
415 test_must_fail git add init/a
419 test_expect_success
'gracefully add submodule with a trailing slash' '
422 git commit -m "commit subproject" init &&
426 git diff --exit-code --cached init &&
428 git commit -m update a >/dev/null &&
429 git rev-parse HEAD) &&
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' '
447 git checkout initial &&
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' '
463 git commit -m "repo commit 1"
465 git clone --bare repo/ bare.git &&
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
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' '
671 cp pristine-.git-config .git/config &&
672 cp pristine-.gitmodules .gitmodules &&
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' '
685 git submodule status >expect
687 mv addtest 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' '
700 echo "$submodurl/repo" >expect &&
701 git config remote.origin.url >actual &&
702 test_cmp expect actual &&
703 echo "gitdir: ../.git/modules/repo" >expect &&
708 git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
710 echo "gitdir: ../.git/modules/submod" >expect &&
711 test_cmp expect submod/.git &&
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 &&
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' '
745 test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" 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 &&
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