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