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