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