t / t7400-submodule-basic.shon commit revision: do not peel tags used in range notation (895c5ba)
   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 'setup - initial commit' '
  15        >t &&
  16        git add t &&
  17        git commit -m "initial commit" &&
  18        git branch initial
  19'
  20
  21test_expect_success 'setup - repository in init subdirectory' '
  22        mkdir init &&
  23        (
  24                cd init &&
  25                git init &&
  26                echo a >a &&
  27                git add a &&
  28                git commit -m "submodule commit 1" &&
  29                git tag -a -m "rev-1" rev-1
  30        )
  31'
  32
  33test_expect_success 'setup - commit with gitlink' '
  34        echo a >a &&
  35        echo z >z &&
  36        git add a init z &&
  37        git commit -m "super commit 1"
  38'
  39
  40test_expect_success 'setup - hide init subdirectory' '
  41        mv init .subrepo
  42'
  43
  44test_expect_success 'setup - repository to add submodules to' '
  45        git init addtest &&
  46        git init addtest-ignore
  47'
  48
  49# The 'submodule add' tests need some repository to add as a submodule.
  50# The trash directory is a good one as any. We need to canonicalize
  51# the name, though, as some tests compare it to the absolute path git
  52# generates, which will expand symbolic links.
  53submodurl=$(pwd -P)
  54
  55listbranches() {
  56        git for-each-ref --format='%(refname)' 'refs/heads/*'
  57}
  58
  59inspect() {
  60        dir=$1 &&
  61        dotdot="${2:-..}" &&
  62
  63        (
  64                cd "$dir" &&
  65                listbranches >"$dotdot/heads" &&
  66                { git symbolic-ref HEAD || :; } >"$dotdot/head" &&
  67                git rev-parse HEAD >"$dotdot/head-sha1" &&
  68                git update-index --refresh &&
  69                git diff-files --exit-code &&
  70                git clean -n -d -x >"$dotdot/untracked"
  71        )
  72}
  73
  74test_expect_success 'submodule add' '
  75        echo "refs/heads/master" >expect &&
  76        >empty &&
  77
  78        (
  79                cd addtest &&
  80                git submodule add -q "$submodurl" submod >actual &&
  81                test ! -s actual &&
  82                echo "gitdir: ../.git/modules/submod" >expect &&
  83                test_cmp expect submod/.git &&
  84                (
  85                        cd submod &&
  86                        git config core.worktree >actual &&
  87                        echo "../../../submod" >expect &&
  88                        test_cmp expect actual &&
  89                        rm -f actual expect
  90                ) &&
  91                git submodule init
  92        ) &&
  93
  94        rm -f heads head untracked &&
  95        inspect addtest/submod ../.. &&
  96        test_cmp expect heads &&
  97        test_cmp expect head &&
  98        test_cmp empty untracked
  99'
 100
 101test_expect_success 'submodule add to .gitignored path fails' '
 102        (
 103                cd addtest-ignore &&
 104                cat <<-\EOF >expect &&
 105                The following path is ignored by one of your .gitignore files:
 106                submod
 107                Use -f if you really want to add it.
 108                EOF
 109                # Does not use test_commit due to the ignore
 110                echo "*" > .gitignore &&
 111                git add --force .gitignore &&
 112                git commit -m"Ignore everything" &&
 113                ! git submodule add "$submodurl" submod >actual 2>&1 &&
 114                test_i18ncmp expect actual
 115        )
 116'
 117
 118test_expect_success 'submodule add to .gitignored path with --force' '
 119        (
 120                cd addtest-ignore &&
 121                git submodule add --force "$submodurl" submod
 122        )
 123'
 124
 125test_expect_success 'submodule add --branch' '
 126        echo "refs/heads/initial" >expect-head &&
 127        cat <<-\EOF >expect-heads &&
 128        refs/heads/initial
 129        refs/heads/master
 130        EOF
 131        >empty &&
 132
 133        (
 134                cd addtest &&
 135                git submodule add -b initial "$submodurl" submod-branch &&
 136                git submodule init
 137        ) &&
 138
 139        rm -f heads head untracked &&
 140        inspect addtest/submod-branch ../.. &&
 141        test_cmp expect-heads heads &&
 142        test_cmp expect-head head &&
 143        test_cmp empty untracked
 144'
 145
 146test_expect_success 'submodule add with ./ in path' '
 147        echo "refs/heads/master" >expect &&
 148        >empty &&
 149
 150        (
 151                cd addtest &&
 152                git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
 153                git submodule init
 154        ) &&
 155
 156        rm -f heads head untracked &&
 157        inspect addtest/dotsubmod/frotz ../../.. &&
 158        test_cmp expect heads &&
 159        test_cmp expect head &&
 160        test_cmp empty untracked
 161'
 162
 163test_expect_success 'submodule add with // in path' '
 164        echo "refs/heads/master" >expect &&
 165        >empty &&
 166
 167        (
 168                cd addtest &&
 169                git submodule add "$submodurl" slashslashsubmod///frotz// &&
 170                git submodule init
 171        ) &&
 172
 173        rm -f heads head untracked &&
 174        inspect addtest/slashslashsubmod/frotz ../../.. &&
 175        test_cmp expect heads &&
 176        test_cmp expect head &&
 177        test_cmp empty untracked
 178'
 179
 180test_expect_success 'submodule add with /.. in path' '
 181        echo "refs/heads/master" >expect &&
 182        >empty &&
 183
 184        (
 185                cd addtest &&
 186                git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
 187                git submodule init
 188        ) &&
 189
 190        rm -f heads head untracked &&
 191        inspect addtest/realsubmod ../.. &&
 192        test_cmp expect heads &&
 193        test_cmp expect head &&
 194        test_cmp empty untracked
 195'
 196
 197test_expect_success 'submodule add with ./, /.. and // in path' '
 198        echo "refs/heads/master" >expect &&
 199        >empty &&
 200
 201        (
 202                cd addtest &&
 203                git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
 204                git submodule init
 205        ) &&
 206
 207        rm -f heads head untracked &&
 208        inspect addtest/realsubmod2 ../.. &&
 209        test_cmp expect heads &&
 210        test_cmp expect head &&
 211        test_cmp empty untracked
 212'
 213
 214test_expect_success 'setup - add an example entry to .gitmodules' '
 215        GIT_CONFIG=.gitmodules \
 216        git config submodule.example.url git://example.com/init.git
 217'
 218
 219test_expect_success 'status should fail for unmapped paths' '
 220        test_must_fail git submodule status
 221'
 222
 223test_expect_success 'setup - map path in .gitmodules' '
 224        cat <<\EOF >expect &&
 225[submodule "example"]
 226        url = git://example.com/init.git
 227        path = init
 228EOF
 229
 230        GIT_CONFIG=.gitmodules git config submodule.example.path init &&
 231
 232        test_cmp expect .gitmodules
 233'
 234
 235test_expect_success 'status should only print one line' '
 236        git submodule status >lines &&
 237        test_line_count = 1 lines
 238'
 239
 240test_expect_success 'setup - fetch commit name from submodule' '
 241        rev1=$(cd .subrepo && git rev-parse HEAD) &&
 242        printf "rev1: %s\n" "$rev1" &&
 243        test -n "$rev1"
 244'
 245
 246test_expect_success 'status should initially be "missing"' '
 247        git submodule status >lines &&
 248        grep "^-$rev1" lines
 249'
 250
 251test_expect_success 'init should register submodule url in .git/config' '
 252        echo git://example.com/init.git >expect &&
 253
 254        git submodule init &&
 255        git config submodule.example.url >url &&
 256        git config submodule.example.url ./.subrepo &&
 257
 258        test_cmp expect url
 259'
 260
 261test_failure_with_unknown_submodule () {
 262        test_must_fail git submodule $1 no-such-submodule 2>output.err &&
 263        grep "^error: .*no-such-submodule" output.err
 264}
 265
 266test_expect_success 'init should fail with unknown submodule' '
 267        test_failure_with_unknown_submodule init
 268'
 269
 270test_expect_success 'update should fail with unknown submodule' '
 271        test_failure_with_unknown_submodule update
 272'
 273
 274test_expect_success 'status should fail with unknown submodule' '
 275        test_failure_with_unknown_submodule status
 276'
 277
 278test_expect_success 'sync should fail with unknown submodule' '
 279        test_failure_with_unknown_submodule sync
 280'
 281
 282test_expect_success 'update should fail when path is used by a file' '
 283        echo hello >expect &&
 284
 285        echo "hello" >init &&
 286        test_must_fail git submodule update &&
 287
 288        test_cmp expect init
 289'
 290
 291test_expect_success 'update should fail when path is used by a nonempty directory' '
 292        echo hello >expect &&
 293
 294        rm -fr init &&
 295        mkdir init &&
 296        echo "hello" >init/a &&
 297
 298        test_must_fail git submodule update &&
 299
 300        test_cmp expect init/a
 301'
 302
 303test_expect_success 'update should work when path is an empty dir' '
 304        rm -fr init &&
 305        rm -f head-sha1 &&
 306        echo "$rev1" >expect &&
 307
 308        mkdir init &&
 309        git submodule update -q >update.out &&
 310        test ! -s update.out &&
 311
 312        inspect init &&
 313        test_cmp expect head-sha1
 314'
 315
 316test_expect_success 'status should be "up-to-date" after update' '
 317        git submodule status >list &&
 318        grep "^ $rev1" list
 319'
 320
 321test_expect_success 'status should be "modified" after submodule commit' '
 322        (
 323                cd init &&
 324                echo b >b &&
 325                git add b &&
 326                git commit -m "submodule commit 2"
 327        ) &&
 328
 329        rev2=$(cd init && git rev-parse HEAD) &&
 330        test -n "$rev2" &&
 331        git submodule status >list &&
 332
 333        grep "^+$rev2" list
 334'
 335
 336test_expect_success 'the --cached sha1 should be rev1' '
 337        git submodule --cached status >list &&
 338        grep "^+$rev1" list
 339'
 340
 341test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
 342        git diff >diff &&
 343        grep "^+Subproject commit $rev2" diff
 344'
 345
 346test_expect_success 'update should checkout rev1' '
 347        rm -f head-sha1 &&
 348        echo "$rev1" >expect &&
 349
 350        git submodule update init &&
 351        inspect init &&
 352
 353        test_cmp expect head-sha1
 354'
 355
 356test_expect_success 'status should be "up-to-date" after update' '
 357        git submodule status >list &&
 358        grep "^ $rev1" list
 359'
 360
 361test_expect_success 'checkout superproject with subproject already present' '
 362        git checkout initial &&
 363        git checkout master
 364'
 365
 366test_expect_success 'apply submodule diff' '
 367        >empty &&
 368
 369        git branch second &&
 370        (
 371                cd init &&
 372                echo s >s &&
 373                git add s &&
 374                git commit -m "change subproject"
 375        ) &&
 376        git update-index --add init &&
 377        git commit -m "change init" &&
 378        git format-patch -1 --stdout >P.diff &&
 379        git checkout second &&
 380        git apply --index P.diff &&
 381
 382        git diff --cached master >staged &&
 383        test_cmp empty staged
 384'
 385
 386test_expect_success 'update --init' '
 387        mv init init2 &&
 388        git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
 389        git config --remove-section submodule.example &&
 390        test_must_fail git config submodule.example.url &&
 391
 392        git submodule update init > update.out &&
 393        cat update.out &&
 394        test_i18ngrep "not initialized" update.out &&
 395        test_must_fail git rev-parse --resolve-git-dir init/.git &&
 396
 397        git submodule update --init init &&
 398        git rev-parse --resolve-git-dir init/.git
 399'
 400
 401test_expect_success 'do not add files from a submodule' '
 402
 403        git reset --hard &&
 404        test_must_fail git add init/a
 405
 406'
 407
 408test_expect_success 'gracefully add submodule with a trailing slash' '
 409
 410        git reset --hard &&
 411        git commit -m "commit subproject" init &&
 412        (cd init &&
 413         echo b > a) &&
 414        git add init/ &&
 415        git diff --exit-code --cached init &&
 416        commit=$(cd init &&
 417         git commit -m update a >/dev/null &&
 418         git rev-parse HEAD) &&
 419        git add init/ &&
 420        test_must_fail git diff --exit-code --cached init &&
 421        test $commit = $(git ls-files --stage |
 422                sed -n "s/^160000 \([^ ]*\).*/\1/p")
 423
 424'
 425
 426test_expect_success 'ls-files gracefully handles trailing slash' '
 427
 428        test "init" = "$(git ls-files init/)"
 429
 430'
 431
 432test_expect_success 'moving to a commit without submodule does not leave empty dir' '
 433        rm -rf init &&
 434        mkdir init &&
 435        git reset --hard &&
 436        git checkout initial &&
 437        test ! -d init &&
 438        git checkout second
 439'
 440
 441test_expect_success 'submodule <invalid-subcommand> fails' '
 442        test_must_fail git submodule no-such-subcommand
 443'
 444
 445test_expect_success 'add submodules without specifying an explicit path' '
 446        mkdir repo &&
 447        (
 448                cd repo &&
 449                git init &&
 450                echo r >r &&
 451                git add r &&
 452                git commit -m "repo commit 1"
 453        ) &&
 454        git clone --bare repo/ bare.git &&
 455        (
 456                cd addtest &&
 457                git submodule add "$submodurl/repo" &&
 458                git config -f .gitmodules submodule.repo.path repo &&
 459                git submodule add "$submodurl/bare.git" &&
 460                git config -f .gitmodules submodule.bare.path bare
 461        )
 462'
 463
 464test_expect_success 'add should fail when path is used by a file' '
 465        (
 466                cd addtest &&
 467                touch file &&
 468                test_must_fail  git submodule add "$submodurl/repo" file
 469        )
 470'
 471
 472test_expect_success 'add should fail when path is used by an existing directory' '
 473        (
 474                cd addtest &&
 475                mkdir empty-dir &&
 476                test_must_fail git submodule add "$submodurl/repo" empty-dir
 477        )
 478'
 479
 480test_expect_success 'use superproject as upstream when path is relative and no url is set there' '
 481        (
 482                cd addtest &&
 483                git submodule add ../repo relative &&
 484                test "$(git config -f .gitmodules submodule.relative.url)" = ../repo &&
 485                git submodule sync relative &&
 486                test "$(git config submodule.relative.url)" = "$submodurl/repo"
 487        )
 488'
 489
 490test_expect_success 'set up for relative path tests' '
 491        mkdir reltest &&
 492        (
 493                cd reltest &&
 494                git init &&
 495                mkdir sub &&
 496                (
 497                        cd sub &&
 498                        git init &&
 499                        test_commit foo
 500                ) &&
 501                git add sub &&
 502                git config -f .gitmodules submodule.sub.path sub &&
 503                git config -f .gitmodules submodule.sub.url ../subrepo &&
 504                cp .git/config pristine-.git-config &&
 505                cp .gitmodules pristine-.gitmodules
 506        )
 507'
 508
 509test_expect_success '../subrepo works with URL - ssh://hostname/repo' '
 510        (
 511                cd reltest &&
 512                cp pristine-.git-config .git/config &&
 513                cp pristine-.gitmodules .gitmodules &&
 514                git config remote.origin.url ssh://hostname/repo &&
 515                git submodule init &&
 516                test "$(git config submodule.sub.url)" = ssh://hostname/subrepo
 517        )
 518'
 519
 520test_expect_success '../subrepo works with port-qualified URL - ssh://hostname:22/repo' '
 521        (
 522                cd reltest &&
 523                cp pristine-.git-config .git/config &&
 524                cp pristine-.gitmodules .gitmodules &&
 525                git config remote.origin.url ssh://hostname:22/repo &&
 526                git submodule init &&
 527                test "$(git config submodule.sub.url)" = ssh://hostname:22/subrepo
 528        )
 529'
 530
 531# About the choice of the path in the next test:
 532# - double-slash side-steps path mangling issues on Windows
 533# - it is still an absolute local path
 534# - there cannot be a server with a blank in its name just in case the
 535#   path is used erroneously to access a //server/share style path
 536test_expect_success '../subrepo path works with local path - //somewhere else/repo' '
 537        (
 538                cd reltest &&
 539                cp pristine-.git-config .git/config &&
 540                cp pristine-.gitmodules .gitmodules &&
 541                git config remote.origin.url "//somewhere else/repo" &&
 542                git submodule init &&
 543                test "$(git config submodule.sub.url)" = "//somewhere else/subrepo"
 544        )
 545'
 546
 547test_expect_success '../subrepo works with file URL - file:///tmp/repo' '
 548        (
 549                cd reltest &&
 550                cp pristine-.git-config .git/config &&
 551                cp pristine-.gitmodules .gitmodules &&
 552                git config remote.origin.url file:///tmp/repo &&
 553                git submodule init &&
 554                test "$(git config submodule.sub.url)" = file:///tmp/subrepo
 555        )
 556'
 557
 558test_expect_success '../subrepo works with helper URL- helper:://hostname/repo' '
 559        (
 560                cd reltest &&
 561                cp pristine-.git-config .git/config &&
 562                cp pristine-.gitmodules .gitmodules &&
 563                git config remote.origin.url helper:://hostname/repo &&
 564                git submodule init &&
 565                test "$(git config submodule.sub.url)" = helper:://hostname/subrepo
 566        )
 567'
 568
 569test_expect_success '../subrepo works with scp-style URL - user@host:repo' '
 570        (
 571                cd reltest &&
 572                cp pristine-.git-config .git/config &&
 573                git config remote.origin.url user@host:repo &&
 574                git submodule init &&
 575                test "$(git config submodule.sub.url)" = user@host:subrepo
 576        )
 577'
 578
 579test_expect_success '../subrepo works with scp-style URL - user@host:path/to/repo' '
 580        (
 581                cd reltest &&
 582                cp pristine-.git-config .git/config &&
 583                cp pristine-.gitmodules .gitmodules &&
 584                git config remote.origin.url user@host:path/to/repo &&
 585                git submodule init &&
 586                test "$(git config submodule.sub.url)" = user@host:path/to/subrepo
 587        )
 588'
 589
 590test_expect_success '../subrepo works with relative local path - foo' '
 591        (
 592                cd reltest &&
 593                cp pristine-.git-config .git/config &&
 594                cp pristine-.gitmodules .gitmodules &&
 595                git config remote.origin.url foo &&
 596                # actual: fails with an error
 597                git submodule init &&
 598                test "$(git config submodule.sub.url)" = subrepo
 599        )
 600'
 601
 602test_expect_success '../subrepo works with relative local path - foo/bar' '
 603        (
 604                cd reltest &&
 605                cp pristine-.git-config .git/config &&
 606                cp pristine-.gitmodules .gitmodules &&
 607                git config remote.origin.url foo/bar &&
 608                git submodule init &&
 609                test "$(git config submodule.sub.url)" = foo/subrepo
 610        )
 611'
 612
 613test_expect_success '../subrepo works with relative local path - ./foo' '
 614        (
 615                cd reltest &&
 616                cp pristine-.git-config .git/config &&
 617                cp pristine-.gitmodules .gitmodules &&
 618                git config remote.origin.url ./foo &&
 619                git submodule init &&
 620                test "$(git config submodule.sub.url)" = subrepo
 621        )
 622'
 623
 624test_expect_success '../subrepo works with relative local path - ./foo/bar' '
 625        (
 626                cd reltest &&
 627                cp pristine-.git-config .git/config &&
 628                cp pristine-.gitmodules .gitmodules &&
 629                git config remote.origin.url ./foo/bar &&
 630                git submodule init &&
 631                test "$(git config submodule.sub.url)" = foo/subrepo
 632        )
 633'
 634
 635test_expect_success '../subrepo works with relative local path - ../foo' '
 636        (
 637                cd reltest &&
 638                cp pristine-.git-config .git/config &&
 639                cp pristine-.gitmodules .gitmodules &&
 640                git config remote.origin.url ../foo &&
 641                git submodule init &&
 642                test "$(git config submodule.sub.url)" = ../subrepo
 643        )
 644'
 645
 646test_expect_success '../subrepo works with relative local path - ../foo/bar' '
 647        (
 648                cd reltest &&
 649                cp pristine-.git-config .git/config &&
 650                cp pristine-.gitmodules .gitmodules &&
 651                git config remote.origin.url ../foo/bar &&
 652                git submodule init &&
 653                test "$(git config submodule.sub.url)" = ../foo/subrepo
 654        )
 655'
 656
 657test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.git' '
 658        (
 659                cd reltest &&
 660                cp pristine-.git-config .git/config &&
 661                cp pristine-.gitmodules .gitmodules &&
 662                mkdir -p a/b/c &&
 663                (cd a/b/c; git init) &&
 664                git config remote.origin.url ../foo/bar.git &&
 665                git submodule add ../bar/a/b/c ./a/b/c &&
 666                git submodule init &&
 667                test "$(git config submodule.a/b/c.url)" = ../foo/bar/a/b/c
 668        )
 669'
 670
 671test_expect_success 'moving the superproject does not break submodules' '
 672        (
 673                cd addtest &&
 674                git submodule status >expect
 675        )
 676        mv addtest addtest2 &&
 677        (
 678                cd addtest2 &&
 679                git submodule status >actual &&
 680                test_cmp expect actual
 681        )
 682'
 683
 684test_done