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