1#!/bin/sh 2# 3# Copyright (c) 2007 Lars Hjemli 4# 5 6test_description='Basic porcelain support for submodules 7 8This test tries to verify basic sanity of the init, update and status 9subcommands of git submodule. 10' 11 12GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 13export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 14 15. ./test-lib.sh 16 17test_expect_success 'submodule deinit works on empty repository' ' 18 git submodule deinit --all 19' 20 21test_expect_success 'setup - initial commit' ' 22 >t && 23 git add t && 24 git commit -m "initial commit" && 25 git branch initial 26' 27 28test_expect_success 'submodule init aborts on missing .gitmodules file' ' 29 test_when_finished "git update-index --remove sub" && 30 git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub && 31 # missing the .gitmodules file here 32 test_must_fail git submodule init 2>actual && 33 test_i18ngrep "No url found for submodule path" actual 34' 35 36test_expect_success 'submodule update aborts on missing .gitmodules file' ' 37 test_when_finished "git update-index --remove sub" && 38 git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub && 39 # missing the .gitmodules file here 40 git submodule update sub 2>actual && 41 test_i18ngrep "Submodule path .sub. not initialized" actual 42' 43 44test_expect_success 'submodule update aborts on missing gitmodules url' ' 45 test_when_finished "git update-index --remove sub" && 46 git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub && 47 test_when_finished "rm -f .gitmodules" && 48 git config -f .gitmodules submodule.s.path sub && 49 test_must_fail git submodule init 50' 51 52test_expect_success 'add aborts on repository with no commits' ' 53 cat >expect <<-\EOF && 54 fatal: '"'repo-no-commits'"' does not have a commit checked out 55 EOF 56 git init repo-no-commits && 57 test_must_fail git submodule add ../a ./repo-no-commits 2>actual && 58 test_cmp expect actual 59' 60 61test_expect_success 'status should ignore inner git repo when not added' ' 62 rm -fr inner && 63 mkdir inner && 64 ( 65 cd inner && 66 git init && 67 >t && 68 git add t && 69 git commit -m "initial" 70 ) && 71 test_must_fail git submodule status inner 2>output.err && 72 rm -fr inner && 73 test_i18ngrep "^error: .*did not match any file(s) known to git" output.err 74' 75 76test_expect_success 'setup - repository in init subdirectory' ' 77 mkdir init && 78 ( 79 cd init && 80 git init && 81 echo a >a && 82 git add a && 83 git commit -m "submodule commit 1" && 84 git tag -a -m "rev-1" rev-1 85 ) 86' 87 88test_expect_success 'setup - commit with gitlink' ' 89 echo a >a && 90 echo z >z && 91 git add a init z && 92 git commit -m "super commit 1" 93' 94 95test_expect_success 'setup - hide init subdirectory' ' 96 mv init .subrepo 97' 98 99test_expect_success 'setup - repository to add submodules to' ' 100 git init addtest && 101 git init addtest-ignore 102' 103 104# The 'submodule add' tests need some repository to add as a submodule. 105# The trash directory is a good one as any. We need to canonicalize 106# the name, though, as some tests compare it to the absolute path git 107# generates, which will expand symbolic links. 108submodurl=$(pwd -P) 109 110listbranches() { 111 git for-each-ref --format='%(refname)' 'refs/heads/*' 112} 113 114inspect() { 115 dir=$1 && 116 dotdot="${2:-..}" && 117 118 ( 119 cd "$dir" && 120 listbranches >"$dotdot/heads" && 121 { git symbolic-ref HEAD || :; } >"$dotdot/head" && 122 git rev-parse HEAD >"$dotdot/head-sha1" && 123 git update-index --refresh && 124 git diff-files --exit-code && 125 git clean -n -d -x >"$dotdot/untracked" 126 ) 127} 128 129test_expect_success 'submodule add' ' 130 echo "refs/heads/main" >expect && 131 132 ( 133 cd addtest && 134 git submodule add -q "$submodurl" submod >actual && 135 test_must_be_empty actual && 136 echo "gitdir: ../.git/modules/submod" >expect && 137 test_cmp expect submod/.git && 138 ( 139 cd submod && 140 git config core.worktree >actual && 141 echo "../../../submod" >expect && 142 test_cmp expect actual && 143 rm -f actual expect 144 ) && 145 git submodule init 146 ) && 147 148 rm -f heads head untracked && 149 inspect addtest/submod ../.. && 150 test_cmp expect heads && 151 test_cmp expect head && 152 test_must_be_empty untracked 153' 154 155test_expect_success 'setup parent and one repository' ' 156 test_create_repo parent && 157 test_commit -C parent one 158' 159 160test_expect_success 'redirected submodule add does not show progress' ' 161 git -C addtest submodule add "file://$submodurl/parent" submod-redirected \ 162 2>err && 163 ! grep % err && 164 test_i18ngrep ! "Checking connectivity" err 165' 166 167test_expect_success 'redirected submodule add --progress does show progress' ' 168 git -C addtest submodule add --progress "file://$submodurl/parent" \ 169 submod-redirected-progress 2>err && \ 170 grep % err 171' 172 173test_expect_success 'submodule add to .gitignored path fails' ' 174 ( 175 cd addtest-ignore && 176 cat <<-\EOF >expect && 177 The following paths are ignored by one of your .gitignore files: 178 submod 179 hint: Use -f if you really want to add them. 180 hint: Turn this message off by running 181 hint: "git config advice.addIgnoredFile false" 182 EOF 183 # Does not use test_commit due to the ignore 184 echo "*" > .gitignore && 185 git add --force .gitignore && 186 git commit -m"Ignore everything" && 187 ! git submodule add "$submodurl" submod >actual 2>&1 && 188 test_cmp expect actual 189 ) 190' 191 192test_expect_success 'submodule add to .gitignored path with --force' ' 193 ( 194 cd addtest-ignore && 195 git submodule add --force "$submodurl" submod 196 ) 197' 198 199test_expect_success 'submodule add to path with tracked content fails' ' 200 ( 201 cd addtest && 202 echo "fatal: '\''dir-tracked'\'' already exists in the index" >expect && 203 mkdir dir-tracked && 204 test_commit foo dir-tracked/bar && 205 test_must_fail git submodule add "$submodurl" dir-tracked >actual 2>&1 && 206 test_cmp expect actual 207 ) 208' 209 210test_expect_success 'submodule add to reconfigure existing submodule with --force' ' 211 ( 212 cd addtest-ignore && 213 bogus_url="$(pwd)/bogus-url" && 214 git submodule add --force "$bogus_url" submod && 215 git submodule add --force -b initial "$submodurl" submod-branch && 216 test "$bogus_url" = "$(git config -f .gitmodules submodule.submod.url)" && 217 test "$bogus_url" = "$(git config submodule.submod.url)" && 218 # Restore the url 219 git submodule add --force "$submodurl" submod && 220 test "$submodurl" = "$(git config -f .gitmodules submodule.submod.url)" && 221 test "$submodurl" = "$(git config submodule.submod.url)" 222 ) 223' 224 225test_expect_success 'submodule add relays add --dry-run stderr' ' 226 test_when_finished "rm -rf addtest/.git/index.lock" && 227 ( 228 cd addtest && 229 : >.git/index.lock && 230 ! git submodule add "$submodurl" sub-while-locked 2>output.err && 231 test_i18ngrep "^fatal: .*index\.lock" output.err && 232 test_path_is_missing sub-while-locked 233 ) 234' 235 236test_expect_success 'submodule add --branch' ' 237 echo "refs/heads/initial" >expect-head && 238 cat <<-\EOF >expect-heads && 239 refs/heads/initial 240 refs/heads/main 241 EOF 242 243 ( 244 cd addtest && 245 git submodule add -b initial "$submodurl" submod-branch && 246 test "initial" = "$(git config -f .gitmodules submodule.submod-branch.branch)" && 247 git submodule init 248 ) && 249 250 rm -f heads head untracked && 251 inspect addtest/submod-branch ../.. && 252 test_cmp expect-heads heads && 253 test_cmp expect-head head && 254 test_must_be_empty untracked 255' 256 257test_expect_success 'submodule add with ./ in path' ' 258 echo "refs/heads/main" >expect && 259 260 ( 261 cd addtest && 262 git submodule add "$submodurl" ././dotsubmod/./frotz/./ && 263 git submodule init 264 ) && 265 266 rm -f heads head untracked && 267 inspect addtest/dotsubmod/frotz ../../.. && 268 test_cmp expect heads && 269 test_cmp expect head && 270 test_must_be_empty untracked 271' 272 273test_expect_success 'submodule add with /././ in path' ' 274 echo "refs/heads/main" >expect && 275 276 ( 277 cd addtest && 278 git submodule add "$submodurl" dotslashdotsubmod/././frotz/./ && 279 git submodule init 280 ) && 281 282 rm -f heads head untracked && 283 inspect addtest/dotslashdotsubmod/frotz ../../.. && 284 test_cmp expect heads && 285 test_cmp expect head && 286 test_must_be_empty untracked 287' 288 289test_expect_success 'submodule add with // in path' ' 290 echo "refs/heads/main" >expect && 291 292 ( 293 cd addtest && 294 git submodule add "$submodurl" slashslashsubmod///frotz// && 295 git submodule init 296 ) && 297 298 rm -f heads head untracked && 299 inspect addtest/slashslashsubmod/frotz ../../.. && 300 test_cmp expect heads && 301 test_cmp expect head && 302 test_must_be_empty untracked 303' 304 305test_expect_success 'submodule add with /.. in path' ' 306 echo "refs/heads/main" >expect && 307 308 ( 309 cd addtest && 310 git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. && 311 git submodule init 312 ) && 313 314 rm -f heads head untracked && 315 inspect addtest/realsubmod ../.. && 316 test_cmp expect heads && 317 test_cmp expect head && 318 test_must_be_empty untracked 319' 320 321test_expect_success 'submodule add with ./, /.. and // in path' ' 322 echo "refs/heads/main" >expect && 323 324 ( 325 cd addtest && 326 git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. && 327 git submodule init 328 ) && 329 330 rm -f heads head untracked && 331 inspect addtest/realsubmod2 ../.. && 332 test_cmp expect heads && 333 test_cmp expect head && 334 test_must_be_empty untracked 335' 336 337test_expect_success !CYGWIN 'submodule add with \\ in path' ' 338 test_when_finished "rm -rf parent sub\\with\\backslash" && 339 340 # Initialize a repo with a backslash in its name 341 git init sub\\with\\backslash && 342 touch sub\\with\\backslash/empty.file && 343 git -C sub\\with\\backslash add empty.file && 344 git -C sub\\with\\backslash commit -m "Added empty.file" && 345 346 # Add that repository as a submodule 347 git init parent && 348 git -C parent submodule add ../sub\\with\\backslash 349' 350 351test_expect_success 'submodule add in subdirectory' ' 352 echo "refs/heads/main" >expect && 353 354 mkdir addtest/sub && 355 ( 356 cd addtest/sub && 357 git submodule add "$submodurl" ../realsubmod3 && 358 git submodule init 359 ) && 360 361 rm -f heads head untracked && 362 inspect addtest/realsubmod3 ../.. && 363 test_cmp expect heads && 364 test_cmp expect head && 365 test_must_be_empty untracked 366' 367 368test_expect_success 'submodule add in subdirectory with relative path should fail' ' 369 ( 370 cd addtest/sub && 371 test_must_fail git submodule add ../../ submod3 2>../../output.err 372 ) && 373 test_i18ngrep toplevel output.err 374' 375 376test_expect_success 'setup - add an example entry to .gitmodules' ' 377 git config --file=.gitmodules submodule.example.url git://example.com/init.git 378' 379 380test_expect_success 'status should fail for unmapped paths' ' 381 test_must_fail git submodule status 382' 383 384test_expect_success 'setup - map path in .gitmodules' ' 385 cat <<\EOF >expect && 386[submodule "example"] 387 url = git://example.com/init.git 388 path = init 389EOF 390 391 git config --file=.gitmodules submodule.example.path init && 392 393 test_cmp expect .gitmodules 394' 395 396test_expect_success 'status should only print one line' ' 397 git submodule status >lines && 398 test_line_count = 1 lines 399' 400 401test_expect_success 'status from subdirectory should have the same SHA1' ' 402 test_when_finished "rmdir addtest/subdir" && 403 ( 404 cd addtest && 405 mkdir subdir && 406 git submodule status >output && 407 awk "{print \$1}" <output >expect && 408 cd subdir && 409 git submodule status >../output && 410 awk "{print \$1}" <../output >../actual && 411 test_cmp ../expect ../actual && 412 git -C ../submod checkout HEAD^ && 413 git submodule status >../output && 414 awk "{print \$1}" <../output >../actual2 && 415 cd .. && 416 git submodule status >output && 417 awk "{print \$1}" <output >expect2 && 418 test_cmp expect2 actual2 && 419 ! test_cmp actual actual2 420 ) 421' 422 423test_expect_success 'setup - fetch commit name from submodule' ' 424 rev1=$(cd .subrepo && git rev-parse HEAD) && 425 printf "rev1: %s\n" "$rev1" && 426 test -n "$rev1" 427' 428 429test_expect_success 'status should initially be "missing"' ' 430 git submodule status >lines && 431 grep "^-$rev1" lines 432' 433 434test_expect_success 'init should register submodule url in .git/config' ' 435 echo git://example.com/init.git >expect && 436 437 git submodule init && 438 git config submodule.example.url >url && 439 git config submodule.example.url ./.subrepo && 440 441 test_cmp expect url 442' 443 444test_expect_success 'status should still be "missing" after initializing' ' 445 rm -fr init && 446 mkdir init && 447 git submodule status >lines && 448 rm -fr init && 449 grep "^-$rev1" lines 450' 451 452test_failure_with_unknown_submodule () { 453 test_must_fail git submodule $1 no-such-submodule 2>output.err && 454 test_i18ngrep "^error: .*no-such-submodule" output.err 455} 456 457test_expect_success 'init should fail with unknown submodule' ' 458 test_failure_with_unknown_submodule init 459' 460 461test_expect_success 'update should fail with unknown submodule' ' 462 test_failure_with_unknown_submodule update 463' 464 465test_expect_success 'status should fail with unknown submodule' ' 466 test_failure_with_unknown_submodule status 467' 468 469test_expect_success 'sync should fail with unknown submodule' ' 470 test_failure_with_unknown_submodule sync 471' 472 473test_expect_success 'update should fail when path is used by a file' ' 474 echo hello >expect && 475 476 echo "hello" >init && 477 test_must_fail git submodule update && 478 479 test_cmp expect init 480' 481 482test_expect_success 'update should fail when path is used by a nonempty directory' ' 483 echo hello >expect && 484 485 rm -fr init && 486 mkdir init && 487 echo "hello" >init/a && 488 489 test_must_fail git submodule update && 490 491 test_cmp expect init/a 492' 493 494test_expect_success 'update should work when path is an empty dir' ' 495 rm -fr init && 496 rm -f head-sha1 && 497 echo "$rev1" >expect && 498 499 mkdir init && 500 git submodule update -q >update.out && 501 test_must_be_empty update.out && 502 503 inspect init && 504 test_cmp expect head-sha1 505' 506 507test_expect_success 'status should be "up-to-date" after update' ' 508 git submodule status >list && 509 grep "^ $rev1" list 510' 511 512test_expect_success 'status "up-to-date" from subdirectory' ' 513 mkdir -p sub && 514 ( 515 cd sub && 516 git submodule status >../list 517 ) && 518 grep "^ $rev1" list && 519 grep "\\.\\./init" list 520' 521 522test_expect_success 'status "up-to-date" from subdirectory with path' ' 523 mkdir -p sub && 524 ( 525 cd sub && 526 git submodule status ../init >../list 527 ) && 528 grep "^ $rev1" list && 529 grep "\\.\\./init" list 530' 531 532test_expect_success 'status should be "modified" after submodule commit' ' 533 ( 534 cd init && 535 echo b >b && 536 git add b && 537 git commit -m "submodule commit 2" 538 ) && 539 540 rev2=$(cd init && git rev-parse HEAD) && 541 test -n "$rev2" && 542 git submodule status >list && 543 544 grep "^+$rev2" list 545' 546 547test_expect_success 'the --cached sha1 should be rev1' ' 548 git submodule --cached status >list && 549 grep "^+$rev1" list 550' 551 552test_expect_success 'git diff should report the SHA1 of the new submodule commit' ' 553 git diff >diff && 554 grep "^+Subproject commit $rev2" diff 555' 556 557test_expect_success 'update should checkout rev1' ' 558 rm -f head-sha1 && 559 echo "$rev1" >expect && 560 561 git submodule update init && 562 inspect init && 563 564 test_cmp expect head-sha1 565' 566 567test_expect_success 'status should be "up-to-date" after update' ' 568 git submodule status >list && 569 grep "^ $rev1" list 570' 571 572test_expect_success 'checkout superproject with subproject already present' ' 573 git checkout initial && 574 git checkout main 575' 576 577test_expect_success 'apply submodule diff' ' 578 git branch second && 579 ( 580 cd init && 581 echo s >s && 582 git add s && 583 git commit -m "change subproject" 584 ) && 585 git update-index --add init && 586 git commit -m "change init" && 587 git format-patch -1 --stdout >P.diff && 588 git checkout second && 589 git apply --index P.diff && 590 591 git diff --cached main >staged && 592 test_must_be_empty staged 593' 594 595test_expect_success 'update --init' ' 596 mv init init2 && 597 git config -f .gitmodules submodule.example.url "$(pwd)/init2" && 598 git config --remove-section submodule.example && 599 test_must_fail git config submodule.example.url && 600 601 git submodule update init 2> update.out && 602 test_i18ngrep "not initialized" update.out && 603 test_must_fail git rev-parse --resolve-git-dir init/.git && 604 605 git submodule update --init init && 606 git rev-parse --resolve-git-dir init/.git 607' 608 609test_expect_success 'update --init from subdirectory' ' 610 mv init init2 && 611 git config -f .gitmodules submodule.example.url "$(pwd)/init2" && 612 git config --remove-section submodule.example && 613 test_must_fail git config submodule.example.url && 614 615 mkdir -p sub && 616 ( 617 cd sub && 618 git submodule update ../init 2>update.out && 619 test_i18ngrep "not initialized" update.out && 620 test_must_fail git rev-parse --resolve-git-dir ../init/.git && 621 622 git submodule update --init ../init 623 ) && 624 git rev-parse --resolve-git-dir init/.git 625' 626 627test_expect_success 'do not add files from a submodule' ' 628 629 git reset --hard && 630 test_must_fail git add init/a 631 632' 633 634test_expect_success 'gracefully add/reset submodule with a trailing slash' ' 635 636 git reset --hard && 637 git commit -m "commit subproject" init && 638 (cd init && 639 echo b > a) && 640 git add init/ && 641 git diff --exit-code --cached init && 642 commit=$(cd init && 643 git commit -m update a >/dev/null && 644 git rev-parse HEAD) && 645 git add init/ && 646 test_must_fail git diff --exit-code --cached init && 647 test $commit = $(git ls-files --stage | 648 sed -n "s/^160000 \([^ ]*\).*/\1/p") && 649 git reset init/ && 650 git diff --exit-code --cached init 651 652' 653 654test_expect_success 'ls-files gracefully handles trailing slash' ' 655 656 test "init" = "$(git ls-files init/)" 657 658' 659 660test_expect_success 'moving to a commit without submodule does not leave empty dir' ' 661 rm -rf init && 662 mkdir init && 663 git reset --hard && 664 git checkout initial && 665 test ! -d init && 666 git checkout second 667' 668 669test_expect_success 'submodule <invalid-subcommand> fails' ' 670 test_must_fail git submodule no-such-subcommand 671' 672 673test_expect_success 'add submodules without specifying an explicit path' ' 674 mkdir repo && 675 ( 676 cd repo && 677 git init && 678 echo r >r && 679 git add r && 680 git commit -m "repo commit 1" 681 ) && 682 git clone --bare repo/ bare.git && 683 ( 684 cd addtest && 685 git submodule add "$submodurl/repo" && 686 git config -f .gitmodules submodule.repo.path repo && 687 git submodule add "$submodurl/bare.git" && 688 git config -f .gitmodules submodule.bare.path bare 689 ) 690' 691 692test_expect_success 'add should fail when path is used by a file' ' 693 ( 694 cd addtest && 695 touch file && 696 test_must_fail git submodule add "$submodurl/repo" file 697 ) 698' 699 700test_expect_success 'add should fail when path is used by an existing directory' ' 701 ( 702 cd addtest && 703 mkdir empty-dir && 704 test_must_fail git submodule add "$submodurl/repo" empty-dir 705 ) 706' 707 708test_expect_success 'use superproject as upstream when path is relative and no url is set there' ' 709 ( 710 cd addtest && 711 git submodule add ../repo relative && 712 test "$(git config -f .gitmodules submodule.relative.url)" = ../repo && 713 git submodule sync relative && 714 test "$(git config submodule.relative.url)" = "$submodurl/repo" 715 ) 716' 717 718test_expect_success 'set up for relative path tests' ' 719 mkdir reltest && 720 ( 721 cd reltest && 722 git init && 723 mkdir sub && 724 ( 725 cd sub && 726 git init && 727 test_commit foo 728 ) && 729 git add sub && 730 git config -f .gitmodules submodule.sub.path sub && 731 git config -f .gitmodules submodule.sub.url ../subrepo && 732 cp .git/config pristine-.git-config && 733 cp .gitmodules pristine-.gitmodules 734 ) 735' 736 737test_expect_success '../subrepo works with URL - ssh://hostname/repo' ' 738 ( 739 cd reltest && 740 cp pristine-.git-config .git/config && 741 cp pristine-.gitmodules .gitmodules && 742 git config remote.origin.url ssh://hostname/repo && 743 git submodule init && 744 test "$(git config submodule.sub.url)" = ssh://hostname/subrepo 745 ) 746' 747 748test_expect_success '../subrepo works with port-qualified URL - ssh://hostname:22/repo' ' 749 ( 750 cd reltest && 751 cp pristine-.git-config .git/config && 752 cp pristine-.gitmodules .gitmodules && 753 git config remote.origin.url ssh://hostname:22/repo && 754 git submodule init && 755 test "$(git config submodule.sub.url)" = ssh://hostname:22/subrepo 756 ) 757' 758 759# About the choice of the path in the next test: 760# - double-slash side-steps path mangling issues on Windows 761# - it is still an absolute local path 762# - there cannot be a server with a blank in its name just in case the 763# path is used erroneously to access a //server/share style path 764test_expect_success '../subrepo path works with local path - //somewhere else/repo' ' 765 ( 766 cd reltest && 767 cp pristine-.git-config .git/config && 768 cp pristine-.gitmodules .gitmodules && 769 git config remote.origin.url "//somewhere else/repo" && 770 git submodule init && 771 test "$(git config submodule.sub.url)" = "//somewhere else/subrepo" 772 ) 773' 774 775test_expect_success '../subrepo works with file URL - file:///tmp/repo' ' 776 ( 777 cd reltest && 778 cp pristine-.git-config .git/config && 779 cp pristine-.gitmodules .gitmodules && 780 git config remote.origin.url file:///tmp/repo && 781 git submodule init && 782 test "$(git config submodule.sub.url)" = file:///tmp/subrepo 783 ) 784' 785 786test_expect_success '../subrepo works with helper URL- helper:://hostname/repo' ' 787 ( 788 cd reltest && 789 cp pristine-.git-config .git/config && 790 cp pristine-.gitmodules .gitmodules && 791 git config remote.origin.url helper:://hostname/repo && 792 git submodule init && 793 test "$(git config submodule.sub.url)" = helper:://hostname/subrepo 794 ) 795' 796 797test_expect_success '../subrepo works with scp-style URL - user@host:repo' ' 798 ( 799 cd reltest && 800 cp pristine-.git-config .git/config && 801 git config remote.origin.url user@host:repo && 802 git submodule init && 803 test "$(git config submodule.sub.url)" = user@host:subrepo 804 ) 805' 806 807test_expect_success '../subrepo works with scp-style URL - user@host:path/to/repo' ' 808 ( 809 cd reltest && 810 cp pristine-.git-config .git/config && 811 cp pristine-.gitmodules .gitmodules && 812 git config remote.origin.url user@host:path/to/repo && 813 git submodule init && 814 test "$(git config submodule.sub.url)" = user@host:path/to/subrepo 815 ) 816' 817 818test_expect_success '../subrepo works with relative local path - foo' ' 819 ( 820 cd reltest && 821 cp pristine-.git-config .git/config && 822 cp pristine-.gitmodules .gitmodules && 823 git config remote.origin.url foo && 824 # actual: fails with an error 825 git submodule init && 826 test "$(git config submodule.sub.url)" = subrepo 827 ) 828' 829 830test_expect_success '../subrepo works with relative local path - foo/bar' ' 831 ( 832 cd reltest && 833 cp pristine-.git-config .git/config && 834 cp pristine-.gitmodules .gitmodules && 835 git config remote.origin.url foo/bar && 836 git submodule init && 837 test "$(git config submodule.sub.url)" = foo/subrepo 838 ) 839' 840 841test_expect_success '../subrepo works with relative local path - ./foo' ' 842 ( 843 cd reltest && 844 cp pristine-.git-config .git/config && 845 cp pristine-.gitmodules .gitmodules && 846 git config remote.origin.url ./foo && 847 git submodule init && 848 test "$(git config submodule.sub.url)" = subrepo 849 ) 850' 851 852test_expect_success '../subrepo works with relative local path - ./foo/bar' ' 853 ( 854 cd reltest && 855 cp pristine-.git-config .git/config && 856 cp pristine-.gitmodules .gitmodules && 857 git config remote.origin.url ./foo/bar && 858 git submodule init && 859 test "$(git config submodule.sub.url)" = foo/subrepo 860 ) 861' 862 863test_expect_success '../subrepo works with relative local path - ../foo' ' 864 ( 865 cd reltest && 866 cp pristine-.git-config .git/config && 867 cp pristine-.gitmodules .gitmodules && 868 git config remote.origin.url ../foo && 869 git submodule init && 870 test "$(git config submodule.sub.url)" = ../subrepo 871 ) 872' 873 874test_expect_success '../subrepo works with relative local path - ../foo/bar' ' 875 ( 876 cd reltest && 877 cp pristine-.git-config .git/config && 878 cp pristine-.gitmodules .gitmodules && 879 git config remote.origin.url ../foo/bar && 880 git submodule init && 881 test "$(git config submodule.sub.url)" = ../foo/subrepo 882 ) 883' 884 885test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.git' ' 886 ( 887 cd reltest && 888 cp pristine-.git-config .git/config && 889 cp pristine-.gitmodules .gitmodules && 890 mkdir -p a/b/c && 891 (cd a/b/c && git init && test_commit msg) && 892 git config remote.origin.url ../foo/bar.git && 893 git submodule add ../bar/a/b/c ./a/b/c && 894 git submodule init && 895 test "$(git config submodule.a/b/c.url)" = ../foo/bar/a/b/c 896 ) 897' 898 899test_expect_success 'moving the superproject does not break submodules' ' 900 ( 901 cd addtest && 902 git submodule status >expect 903 ) && 904 mv addtest addtest2 && 905 ( 906 cd addtest2 && 907 git submodule status >actual && 908 test_cmp expect actual 909 ) 910' 911 912test_expect_success 'moving the submodule does not break the superproject' ' 913 ( 914 cd addtest2 && 915 git submodule status 916 ) >actual && 917 sed -e "s/^ \([^ ]* repo\) .*/-\1/" <actual >expect && 918 mv addtest2/repo addtest2/repo.bak && 919 test_when_finished "mv addtest2/repo.bak addtest2/repo" && 920 ( 921 cd addtest2 && 922 git submodule status 923 ) >actual && 924 test_cmp expect actual 925' 926 927test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' ' 928 ( 929 cd addtest2 && 930 ( 931 cd repo && 932 echo "$submodurl/repo" >expect && 933 git config remote.origin.url >actual && 934 test_cmp expect actual && 935 echo "gitdir: ../.git/modules/repo" >expect && 936 test_cmp expect .git 937 ) && 938 rm -rf repo && 939 git rm repo && 940 git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual && 941 test_must_be_empty actual && 942 echo "gitdir: ../.git/modules/submod" >expect && 943 test_cmp expect submod/.git && 944 ( 945 cd repo && 946 echo "$submodurl/bare.git" >expect && 947 git config remote.origin.url >actual && 948 test_cmp expect actual && 949 echo "gitdir: ../.git/modules/repo_new" >expect && 950 test_cmp expect .git 951 ) && 952 echo "repo" >expect && 953 test_must_fail git config -f .gitmodules submodule.repo.path && 954 git config -f .gitmodules submodule.repo_new.path >actual && 955 test_cmp expect actual && 956 echo "$submodurl/repo" >expect && 957 test_must_fail git config -f .gitmodules submodule.repo.url && 958 echo "$submodurl/bare.git" >expect && 959 git config -f .gitmodules submodule.repo_new.url >actual && 960 test_cmp expect actual && 961 echo "$submodurl/repo" >expect && 962 git config submodule.repo.url >actual && 963 test_cmp expect actual && 964 echo "$submodurl/bare.git" >expect && 965 git config submodule.repo_new.url >actual && 966 test_cmp expect actual 967 ) 968' 969 970test_expect_success 'recursive relative submodules stay relative' ' 971 test_when_finished "rm -rf super clone2 subsub sub3" && 972 mkdir subsub && 973 ( 974 cd subsub && 975 git init && 976 >t && 977 git add t && 978 git commit -m "initial commit" 979 ) && 980 mkdir sub3 && 981 ( 982 cd sub3 && 983 git init && 984 >t && 985 git add t && 986 git commit -m "initial commit" && 987 git submodule add ../subsub dirdir/subsub && 988 git commit -m "add submodule subsub" 989 ) && 990 mkdir super && 991 ( 992 cd super && 993 git init && 994 >t && 995 git add t && 996 git commit -m "initial commit" && 997 git submodule add ../sub3 && 998 git commit -m "add submodule sub" 999 ) && 1000 git clone super clone2 && 1001 ( 1002 cd clone2 && 1003 git submodule update --init --recursive && 1004 echo "gitdir: ../.git/modules/sub3" >./sub3/.git_expect && 1005 echo "gitdir: ../../../.git/modules/sub3/modules/dirdir/subsub" >./sub3/dirdir/subsub/.git_expect 1006 ) && 1007 test_cmp clone2/sub3/.git_expect clone2/sub3/.git && 1008 test_cmp clone2/sub3/dirdir/subsub/.git_expect clone2/sub3/dirdir/subsub/.git 1009' 1010 1011test_expect_success 'submodule add with an existing name fails unless forced' ' 1012 ( 1013 cd addtest2 && 1014 rm -rf repo && 1015 git rm repo && 1016 test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" repo && 1017 test ! -d repo && 1018 test_must_fail git config -f .gitmodules submodule.repo_new.path && 1019 test_must_fail git config -f .gitmodules submodule.repo_new.url && 1020 echo "$submodurl/bare.git" >expect && 1021 git config submodule.repo_new.url >actual && 1022 test_cmp expect actual && 1023 git submodule add -f -q --name repo_new "$submodurl/repo.git" repo && 1024 test -d repo && 1025 echo "repo" >expect && 1026 git config -f .gitmodules submodule.repo_new.path >actual && 1027 test_cmp expect actual && 1028 echo "$submodurl/repo.git" >expect && 1029 git config -f .gitmodules submodule.repo_new.url >actual && 1030 test_cmp expect actual && 1031 echo "$submodurl/repo.git" >expect && 1032 git config submodule.repo_new.url >actual && 1033 test_cmp expect actual 1034 ) 1035' 1036 1037test_expect_success 'set up a second submodule' ' 1038 git submodule add ./init2 example2 && 1039 git commit -m "submodule example2 added" 1040' 1041 1042test_expect_success 'submodule deinit works on repository without submodules' ' 1043 test_when_finished "rm -rf newdirectory" && 1044 mkdir newdirectory && 1045 ( 1046 cd newdirectory && 1047 git init && 1048 >file && 1049 git add file && 1050 git commit -m "repo should not be empty" && 1051 git submodule deinit . && 1052 git submodule deinit --all 1053 ) 1054' 1055 1056test_expect_success 'submodule deinit should remove the whole submodule section from .git/config' ' 1057 git config submodule.example.foo bar && 1058 git config submodule.example2.frotz nitfol && 1059 git submodule deinit init && 1060 test -z "$(git config --get-regexp "submodule\.example\.")" && 1061 test -n "$(git config --get-regexp "submodule\.example2\.")" && 1062 test -f example2/.git && 1063 rmdir init 1064' 1065 1066test_expect_success 'submodule deinit should unset core.worktree' ' 1067 test_path_is_file .git/modules/example/config && 1068 test_must_fail git config -f .git/modules/example/config core.worktree 1069' 1070 1071test_expect_success 'submodule deinit from subdirectory' ' 1072 git submodule update --init && 1073 git config submodule.example.foo bar && 1074 mkdir -p sub && 1075 ( 1076 cd sub && 1077 git submodule deinit ../init >../output 1078 ) && 1079 test_i18ngrep "\\.\\./init" output && 1080 test -z "$(git config --get-regexp "submodule\.example\.")" && 1081 test -n "$(git config --get-regexp "submodule\.example2\.")" && 1082 test -f example2/.git && 1083 rmdir init 1084' 1085 1086test_expect_success 'submodule deinit . deinits all initialized submodules' ' 1087 git submodule update --init && 1088 git config submodule.example.foo bar && 1089 git config submodule.example2.frotz nitfol && 1090 test_must_fail git submodule deinit && 1091 git submodule deinit . >actual && 1092 test -z "$(git config --get-regexp "submodule\.example\.")" && 1093 test -z "$(git config --get-regexp "submodule\.example2\.")" && 1094 test_i18ngrep "Cleared directory .init" actual && 1095 test_i18ngrep "Cleared directory .example2" actual && 1096 rmdir init example2 1097' 1098 1099test_expect_success 'submodule deinit --all deinits all initialized submodules' ' 1100 git submodule update --init && 1101 git config submodule.example.foo bar && 1102 git config submodule.example2.frotz nitfol && 1103 test_must_fail git submodule deinit && 1104 git submodule deinit --all >actual && 1105 test -z "$(git config --get-regexp "submodule\.example\.")" && 1106 test -z "$(git config --get-regexp "submodule\.example2\.")" && 1107 test_i18ngrep "Cleared directory .init" actual && 1108 test_i18ngrep "Cleared directory .example2" actual && 1109 rmdir init example2 1110' 1111 1112test_expect_success 'submodule deinit deinits a submodule when its work tree is missing or empty' ' 1113 git submodule update --init && 1114 rm -rf init example2/* example2/.git && 1115 git submodule deinit init example2 >actual && 1116 test -z "$(git config --get-regexp "submodule\.example\.")" && 1117 test -z "$(git config --get-regexp "submodule\.example2\.")" && 1118 test_i18ngrep ! "Cleared directory .init" actual && 1119 test_i18ngrep "Cleared directory .example2" actual && 1120 rmdir init 1121' 1122 1123test_expect_success 'submodule deinit fails when the submodule contains modifications unless forced' ' 1124 git submodule update --init && 1125 echo X >>init/s && 1126 test_must_fail git submodule deinit init && 1127 test -n "$(git config --get-regexp "submodule\.example\.")" && 1128 test -f example2/.git && 1129 git submodule deinit -f init >actual && 1130 test -z "$(git config --get-regexp "submodule\.example\.")" && 1131 test_i18ngrep "Cleared directory .init" actual && 1132 rmdir init 1133' 1134 1135test_expect_success 'submodule deinit fails when the submodule contains untracked files unless forced' ' 1136 git submodule update --init && 1137 echo X >>init/untracked && 1138 test_must_fail git submodule deinit init && 1139 test -n "$(git config --get-regexp "submodule\.example\.")" && 1140 test -f example2/.git && 1141 git submodule deinit -f init >actual && 1142 test -z "$(git config --get-regexp "submodule\.example\.")" && 1143 test_i18ngrep "Cleared directory .init" actual && 1144 rmdir init 1145' 1146 1147test_expect_success 'submodule deinit fails when the submodule HEAD does not match unless forced' ' 1148 git submodule update --init && 1149 ( 1150 cd init && 1151 git checkout HEAD^ 1152 ) && 1153 test_must_fail git submodule deinit init && 1154 test -n "$(git config --get-regexp "submodule\.example\.")" && 1155 test -f example2/.git && 1156 git submodule deinit -f init >actual && 1157 test -z "$(git config --get-regexp "submodule\.example\.")" && 1158 test_i18ngrep "Cleared directory .init" actual && 1159 rmdir init 1160' 1161 1162test_expect_success 'submodule deinit is silent when used on an uninitialized submodule' ' 1163 git submodule update --init && 1164 git submodule deinit init >actual && 1165 test_i18ngrep "Submodule .example. (.*) unregistered for path .init" actual && 1166 test_i18ngrep "Cleared directory .init" actual && 1167 git submodule deinit init >actual && 1168 test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && 1169 test_i18ngrep "Cleared directory .init" actual && 1170 git submodule deinit . >actual && 1171 test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && 1172 test_i18ngrep "Submodule .example2. (.*) unregistered for path .example2" actual && 1173 test_i18ngrep "Cleared directory .init" actual && 1174 git submodule deinit . >actual && 1175 test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && 1176 test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual && 1177 test_i18ngrep "Cleared directory .init" actual && 1178 git submodule deinit --all >actual && 1179 test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && 1180 test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual && 1181 test_i18ngrep "Cleared directory .init" actual && 1182 rmdir init example2 1183' 1184 1185test_expect_success 'submodule deinit fails when submodule has a .git directory even when forced' ' 1186 git submodule update --init && 1187 ( 1188 cd init && 1189 rm .git && 1190 cp -R ../.git/modules/example .git && 1191 GIT_WORK_TREE=. git config --unset core.worktree 1192 ) && 1193 test_must_fail git submodule deinit init && 1194 test_must_fail git submodule deinit -f init && 1195 test -d init/.git && 1196 test -n "$(git config --get-regexp "submodule\.example\.")" 1197' 1198 1199test_expect_success 'submodule with UTF-8 name' ' 1200 svname=$(printf "\303\245 \303\244\303\266") && 1201 mkdir "$svname" && 1202 ( 1203 cd "$svname" && 1204 git init && 1205 >sub && 1206 git add sub && 1207 git commit -m "init sub" 1208 ) && 1209 git submodule add ./"$svname" && 1210 git submodule >&2 && 1211 test -n "$(git submodule | grep "$svname")" 1212' 1213 1214test_expect_success 'submodule add clone shallow submodule' ' 1215 mkdir super && 1216 pwd=$(pwd) && 1217 ( 1218 cd super && 1219 git init && 1220 git submodule add --depth=1 file://"$pwd"/example2 submodule && 1221 ( 1222 cd submodule && 1223 test 1 = $(git log --oneline | wc -l) 1224 ) 1225 ) 1226' 1227 1228test_expect_success 'submodule helper list is not confused by common prefixes' ' 1229 mkdir -p dir1/b && 1230 ( 1231 cd dir1/b && 1232 git init && 1233 echo hi >testfile2 && 1234 git add . && 1235 git commit -m "test1" 1236 ) && 1237 mkdir -p dir2/b && 1238 ( 1239 cd dir2/b && 1240 git init && 1241 echo hello >testfile1 && 1242 git add . && 1243 git commit -m "test2" 1244 ) && 1245 git submodule add /dir1/b dir1/b && 1246 git submodule add /dir2/b dir2/b && 1247 git commit -m "first submodule commit" && 1248 git submodule--helper list dir1/b | cut -f 2 >actual && 1249 echo "dir1/b" >expect && 1250 test_cmp expect actual 1251' 1252 1253test_expect_success 'setup superproject with submodules' ' 1254 git init sub1 && 1255 test_commit -C sub1 test && 1256 test_commit -C sub1 test2 && 1257 git init multisuper && 1258 git -C multisuper submodule add ../sub1 sub0 && 1259 git -C multisuper submodule add ../sub1 sub1 && 1260 git -C multisuper submodule add ../sub1 sub2 && 1261 git -C multisuper submodule add ../sub1 sub3 && 1262 git -C multisuper commit -m "add some submodules" 1263' 1264 1265cat >expect <<-EOF 1266-sub0 1267 sub1 (test2) 1268 sub2 (test2) 1269 sub3 (test2) 1270EOF 1271 1272test_expect_success 'submodule update --init with a specification' ' 1273 test_when_finished "rm -rf multisuper_clone" && 1274 pwd=$(pwd) && 1275 git clone file://"$pwd"/multisuper multisuper_clone && 1276 git -C multisuper_clone submodule update --init . ":(exclude)sub0" && 1277 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1278 test_cmp expect actual 1279' 1280 1281test_expect_success 'submodule update --init with submodule.active set' ' 1282 test_when_finished "rm -rf multisuper_clone" && 1283 pwd=$(pwd) && 1284 git clone file://"$pwd"/multisuper multisuper_clone && 1285 git -C multisuper_clone config submodule.active "." && 1286 git -C multisuper_clone config --add submodule.active ":(exclude)sub0" && 1287 git -C multisuper_clone submodule update --init && 1288 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1289 test_cmp expect actual 1290' 1291 1292test_expect_success 'submodule update and setting submodule.<name>.active' ' 1293 test_when_finished "rm -rf multisuper_clone" && 1294 pwd=$(pwd) && 1295 git clone file://"$pwd"/multisuper multisuper_clone && 1296 git -C multisuper_clone config --bool submodule.sub0.active "true" && 1297 git -C multisuper_clone config --bool submodule.sub1.active "false" && 1298 git -C multisuper_clone config --bool submodule.sub2.active "true" && 1299 1300 cat >expect <<-\EOF && 1301 sub0 (test2) 1302 -sub1 1303 sub2 (test2) 1304 -sub3 1305 EOF 1306 git -C multisuper_clone submodule update && 1307 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1308 test_cmp expect actual 1309' 1310 1311test_expect_success 'clone active submodule without submodule url set' ' 1312 test_when_finished "rm -rf test/test" && 1313 mkdir test && 1314 # another dir breaks accidental relative paths still being correct 1315 git clone file://"$pwd"/multisuper test/test && 1316 ( 1317 cd test/test && 1318 git config submodule.active "." && 1319 1320 # do not pass --init flag, as the submodule is already active: 1321 git submodule update && 1322 git submodule status >actual_raw && 1323 1324 cut -d" " -f3- actual_raw >actual && 1325 cat >expect <<-\EOF && 1326 sub0 (test2) 1327 sub1 (test2) 1328 sub2 (test2) 1329 sub3 (test2) 1330 EOF 1331 test_cmp expect actual 1332 ) 1333' 1334 1335test_expect_success 'clone --recurse-submodules with a pathspec works' ' 1336 test_when_finished "rm -rf multisuper_clone" && 1337 cat >expected <<-\EOF && 1338 sub0 (test2) 1339 -sub1 1340 -sub2 1341 -sub3 1342 EOF 1343 1344 git clone --recurse-submodules="sub0" multisuper multisuper_clone && 1345 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1346 test_cmp expected actual 1347' 1348 1349test_expect_success 'clone with multiple --recurse-submodules options' ' 1350 test_when_finished "rm -rf multisuper_clone" && 1351 cat >expect <<-\EOF && 1352 -sub0 1353 sub1 (test2) 1354 -sub2 1355 sub3 (test2) 1356 EOF 1357 1358 git clone --recurse-submodules="." \ 1359 --recurse-submodules=":(exclude)sub0" \ 1360 --recurse-submodules=":(exclude)sub2" \ 1361 multisuper multisuper_clone && 1362 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1363 test_cmp expect actual 1364' 1365 1366test_expect_success 'clone and subsequent updates correctly auto-initialize submodules' ' 1367 test_when_finished "rm -rf multisuper_clone" && 1368 cat <<-\EOF >expect && 1369 -sub0 1370 sub1 (test2) 1371 -sub2 1372 sub3 (test2) 1373 EOF 1374 1375 cat <<-\EOF >expect2 && 1376 -sub0 1377 sub1 (test2) 1378 -sub2 1379 sub3 (test2) 1380 -sub4 1381 sub5 (test2) 1382 EOF 1383 1384 git clone --recurse-submodules="." \ 1385 --recurse-submodules=":(exclude)sub0" \ 1386 --recurse-submodules=":(exclude)sub2" \ 1387 --recurse-submodules=":(exclude)sub4" \ 1388 multisuper multisuper_clone && 1389 1390 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1391 test_cmp expect actual && 1392 1393 git -C multisuper submodule add ../sub1 sub4 && 1394 git -C multisuper submodule add ../sub1 sub5 && 1395 git -C multisuper commit -m "add more submodules" && 1396 # obtain the new superproject 1397 git -C multisuper_clone pull && 1398 git -C multisuper_clone submodule update --init && 1399 git -C multisuper_clone submodule status | sed "s/$OID_REGEX //" >actual && 1400 test_cmp expect2 actual 1401' 1402 1403test_expect_success 'init properly sets the config' ' 1404 test_when_finished "rm -rf multisuper_clone" && 1405 git clone --recurse-submodules="." \ 1406 --recurse-submodules=":(exclude)sub0" \ 1407 multisuper multisuper_clone && 1408 1409 git -C multisuper_clone submodule init -- sub0 sub1 && 1410 git -C multisuper_clone config --get submodule.sub0.active && 1411 test_must_fail git -C multisuper_clone config --get submodule.sub1.active 1412' 1413 1414test_expect_success 'recursive clone respects -q' ' 1415 test_when_finished "rm -rf multisuper_clone" && 1416 git clone -q --recurse-submodules multisuper multisuper_clone >actual && 1417 test_must_be_empty actual 1418' 1419 1420test_done 1421