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