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