t / t7400-submodule-basic.shon commit submodules: always use a relative path to gitdir (ea115a0)
   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                git submodule init
  85        ) &&
  86
  87        rm -f heads head untracked &&
  88        inspect addtest/submod ../.. &&
  89        test_cmp expect heads &&
  90        test_cmp expect head &&
  91        test_cmp empty untracked
  92'
  93
  94test_expect_success 'submodule add to .gitignored path fails' '
  95        (
  96                cd addtest-ignore &&
  97                cat <<-\EOF >expect &&
  98                The following path is ignored by one of your .gitignore files:
  99                submod
 100                Use -f if you really want to add it.
 101                EOF
 102                # Does not use test_commit due to the ignore
 103                echo "*" > .gitignore &&
 104                git add --force .gitignore &&
 105                git commit -m"Ignore everything" &&
 106                ! git submodule add "$submodurl" submod >actual 2>&1 &&
 107                test_i18ncmp expect actual
 108        )
 109'
 110
 111test_expect_success 'submodule add to .gitignored path with --force' '
 112        (
 113                cd addtest-ignore &&
 114                git submodule add --force "$submodurl" submod
 115        )
 116'
 117
 118test_expect_success 'submodule add --branch' '
 119        echo "refs/heads/initial" >expect-head &&
 120        cat <<-\EOF >expect-heads &&
 121        refs/heads/initial
 122        refs/heads/master
 123        EOF
 124        >empty &&
 125
 126        (
 127                cd addtest &&
 128                git submodule add -b initial "$submodurl" submod-branch &&
 129                git submodule init
 130        ) &&
 131
 132        rm -f heads head untracked &&
 133        inspect addtest/submod-branch ../.. &&
 134        test_cmp expect-heads heads &&
 135        test_cmp expect-head head &&
 136        test_cmp empty untracked
 137'
 138
 139test_expect_success 'submodule add with ./ in path' '
 140        echo "refs/heads/master" >expect &&
 141        >empty &&
 142
 143        (
 144                cd addtest &&
 145                git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
 146                git submodule init
 147        ) &&
 148
 149        rm -f heads head untracked &&
 150        inspect addtest/dotsubmod/frotz ../../.. &&
 151        test_cmp expect heads &&
 152        test_cmp expect head &&
 153        test_cmp empty untracked
 154'
 155
 156test_expect_success 'submodule add with // in path' '
 157        echo "refs/heads/master" >expect &&
 158        >empty &&
 159
 160        (
 161                cd addtest &&
 162                git submodule add "$submodurl" slashslashsubmod///frotz// &&
 163                git submodule init
 164        ) &&
 165
 166        rm -f heads head untracked &&
 167        inspect addtest/slashslashsubmod/frotz ../../.. &&
 168        test_cmp expect heads &&
 169        test_cmp expect head &&
 170        test_cmp empty untracked
 171'
 172
 173test_expect_success 'submodule add with /.. in path' '
 174        echo "refs/heads/master" >expect &&
 175        >empty &&
 176
 177        (
 178                cd addtest &&
 179                git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
 180                git submodule init
 181        ) &&
 182
 183        rm -f heads head untracked &&
 184        inspect addtest/realsubmod ../.. &&
 185        test_cmp expect heads &&
 186        test_cmp expect head &&
 187        test_cmp empty untracked
 188'
 189
 190test_expect_success 'submodule add with ./, /.. and // in path' '
 191        echo "refs/heads/master" >expect &&
 192        >empty &&
 193
 194        (
 195                cd addtest &&
 196                git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
 197                git submodule init
 198        ) &&
 199
 200        rm -f heads head untracked &&
 201        inspect addtest/realsubmod2 ../.. &&
 202        test_cmp expect heads &&
 203        test_cmp expect head &&
 204        test_cmp empty untracked
 205'
 206
 207test_expect_success 'setup - add an example entry to .gitmodules' '
 208        GIT_CONFIG=.gitmodules \
 209        git config submodule.example.url git://example.com/init.git
 210'
 211
 212test_expect_success 'status should fail for unmapped paths' '
 213        test_must_fail git submodule status
 214'
 215
 216test_expect_success 'setup - map path in .gitmodules' '
 217        cat <<\EOF >expect &&
 218[submodule "example"]
 219        url = git://example.com/init.git
 220        path = init
 221EOF
 222
 223        GIT_CONFIG=.gitmodules git config submodule.example.path init &&
 224
 225        test_cmp expect .gitmodules
 226'
 227
 228test_expect_success 'status should only print one line' '
 229        git submodule status >lines &&
 230        test $(wc -l <lines) = 1
 231'
 232
 233test_expect_success 'setup - fetch commit name from submodule' '
 234        rev1=$(cd .subrepo && git rev-parse HEAD) &&
 235        printf "rev1: %s\n" "$rev1" &&
 236        test -n "$rev1"
 237'
 238
 239test_expect_success 'status should initially be "missing"' '
 240        git submodule status >lines &&
 241        grep "^-$rev1" lines
 242'
 243
 244test_expect_success 'init should register submodule url in .git/config' '
 245        echo git://example.com/init.git >expect &&
 246
 247        git submodule init &&
 248        git config submodule.example.url >url &&
 249        git config submodule.example.url ./.subrepo &&
 250
 251        test_cmp expect url
 252'
 253
 254test_expect_success 'update should fail when path is used by a file' '
 255        echo hello >expect &&
 256
 257        echo "hello" >init &&
 258        test_must_fail git submodule update &&
 259
 260        test_cmp expect init
 261'
 262
 263test_expect_success 'update should fail when path is used by a nonempty directory' '
 264        echo hello >expect &&
 265
 266        rm -fr init &&
 267        mkdir init &&
 268        echo "hello" >init/a &&
 269
 270        test_must_fail git submodule update &&
 271
 272        test_cmp expect init/a
 273'
 274
 275test_expect_success 'update should work when path is an empty dir' '
 276        rm -fr init &&
 277        rm -f head-sha1 &&
 278        echo "$rev1" >expect &&
 279
 280        mkdir init &&
 281        git submodule update -q >update.out &&
 282        test ! -s update.out &&
 283
 284        inspect init &&
 285        test_cmp expect head-sha1
 286'
 287
 288test_expect_success 'status should be "up-to-date" after update' '
 289        git submodule status >list &&
 290        grep "^ $rev1" list
 291'
 292
 293test_expect_success 'status should be "modified" after submodule commit' '
 294        (
 295                cd init &&
 296                echo b >b &&
 297                git add b &&
 298                git commit -m "submodule commit 2"
 299        ) &&
 300
 301        rev2=$(cd init && git rev-parse HEAD) &&
 302        test -n "$rev2" &&
 303        git submodule status >list &&
 304
 305        grep "^+$rev2" list
 306'
 307
 308test_expect_success 'the --cached sha1 should be rev1' '
 309        git submodule --cached status >list &&
 310        grep "^+$rev1" list
 311'
 312
 313test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
 314        git diff >diff &&
 315        grep "^+Subproject commit $rev2" diff
 316'
 317
 318test_expect_success 'update should checkout rev1' '
 319        rm -f head-sha1 &&
 320        echo "$rev1" >expect &&
 321
 322        git submodule update init &&
 323        inspect init &&
 324
 325        test_cmp expect head-sha1
 326'
 327
 328test_expect_success 'status should be "up-to-date" after update' '
 329        git submodule status >list &&
 330        grep "^ $rev1" list
 331'
 332
 333test_expect_success 'checkout superproject with subproject already present' '
 334        git checkout initial &&
 335        git checkout master
 336'
 337
 338test_expect_success 'apply submodule diff' '
 339        >empty &&
 340
 341        git branch second &&
 342        (
 343                cd init &&
 344                echo s >s &&
 345                git add s &&
 346                git commit -m "change subproject"
 347        ) &&
 348        git update-index --add init &&
 349        git commit -m "change init" &&
 350        git format-patch -1 --stdout >P.diff &&
 351        git checkout second &&
 352        git apply --index P.diff &&
 353
 354        git diff --cached master >staged &&
 355        test_cmp empty staged
 356'
 357
 358test_expect_success 'update --init' '
 359        mv init init2 &&
 360        git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
 361        git config --remove-section submodule.example &&
 362        test_must_fail git config submodule.example.url &&
 363
 364        git submodule update init > update.out &&
 365        cat update.out &&
 366        test_i18ngrep "not initialized" update.out &&
 367        test_must_fail git rev-parse --resolve-git-dir init/.git &&
 368
 369        git submodule update --init init &&
 370        git rev-parse --resolve-git-dir init/.git
 371'
 372
 373test_expect_success 'do not add files from a submodule' '
 374
 375        git reset --hard &&
 376        test_must_fail git add init/a
 377
 378'
 379
 380test_expect_success 'gracefully add submodule with a trailing slash' '
 381
 382        git reset --hard &&
 383        git commit -m "commit subproject" init &&
 384        (cd init &&
 385         echo b > a) &&
 386        git add init/ &&
 387        git diff --exit-code --cached init &&
 388        commit=$(cd init &&
 389         git commit -m update a >/dev/null &&
 390         git rev-parse HEAD) &&
 391        git add init/ &&
 392        test_must_fail git diff --exit-code --cached init &&
 393        test $commit = $(git ls-files --stage |
 394                sed -n "s/^160000 \([^ ]*\).*/\1/p")
 395
 396'
 397
 398test_expect_success 'ls-files gracefully handles trailing slash' '
 399
 400        test "init" = "$(git ls-files init/)"
 401
 402'
 403
 404test_expect_success 'moving to a commit without submodule does not leave empty dir' '
 405        rm -rf init &&
 406        mkdir init &&
 407        git reset --hard &&
 408        git checkout initial &&
 409        test ! -d init &&
 410        git checkout second
 411'
 412
 413test_expect_success 'submodule <invalid-path> warns' '
 414
 415        git submodule no-such-submodule 2> output.err &&
 416        grep "^error: .*no-such-submodule" output.err
 417
 418'
 419
 420test_expect_success 'add submodules without specifying an explicit path' '
 421        mkdir repo &&
 422        (
 423                cd repo &&
 424                git init &&
 425                echo r >r &&
 426                git add r &&
 427                git commit -m "repo commit 1"
 428        ) &&
 429        git clone --bare repo/ bare.git &&
 430        (
 431                cd addtest &&
 432                git submodule add "$submodurl/repo" &&
 433                git config -f .gitmodules submodule.repo.path repo &&
 434                git submodule add "$submodurl/bare.git" &&
 435                git config -f .gitmodules submodule.bare.path bare
 436        )
 437'
 438
 439test_expect_success 'add should fail when path is used by a file' '
 440        (
 441                cd addtest &&
 442                touch file &&
 443                test_must_fail  git submodule add "$submodurl/repo" file
 444        )
 445'
 446
 447test_expect_success 'add should fail when path is used by an existing directory' '
 448        (
 449                cd addtest &&
 450                mkdir empty-dir &&
 451                test_must_fail git submodule add "$submodurl/repo" empty-dir
 452        )
 453'
 454
 455test_expect_success 'use superproject as upstream when path is relative and no url is set there' '
 456        (
 457                cd addtest &&
 458                git submodule add ../repo relative &&
 459                test "$(git config -f .gitmodules submodule.relative.url)" = ../repo &&
 460                git submodule sync relative &&
 461                test "$(git config submodule.relative.url)" = "$submodurl/repo"
 462        )
 463'
 464
 465test_expect_success 'set up for relative path tests' '
 466        mkdir reltest &&
 467        (
 468                cd reltest &&
 469                git init &&
 470                mkdir sub &&
 471                (
 472                        cd sub &&
 473                        git init &&
 474                        test_commit foo
 475                ) &&
 476                git add sub &&
 477                git config -f .gitmodules submodule.sub.path sub &&
 478                git config -f .gitmodules submodule.sub.url ../subrepo &&
 479                cp .git/config pristine-.git-config
 480        )
 481'
 482
 483test_expect_success 'relative path works with URL' '
 484        (
 485                cd reltest &&
 486                cp pristine-.git-config .git/config &&
 487                git config remote.origin.url ssh://hostname/repo &&
 488                git submodule init &&
 489                test "$(git config submodule.sub.url)" = ssh://hostname/subrepo
 490        )
 491'
 492
 493test_expect_success 'relative path works with user@host:path' '
 494        (
 495                cd reltest &&
 496                cp pristine-.git-config .git/config &&
 497                git config remote.origin.url user@host:repo &&
 498                git submodule init &&
 499                test "$(git config submodule.sub.url)" = user@host:subrepo
 500        )
 501'
 502
 503test_done