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