t / t7400-submodule-basic.shon commit t7400: clarify 'submodule add' tests (a76c944)
   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        rev1=$(cd init && git rev-parse HEAD) &&
  32        printf "rev1: %s\n" "$rev1" &&
  33        test -n "$rev1"
  34'
  35
  36test_expect_success 'setup - commit with gitlink' '
  37        echo a >a &&
  38        echo z >z &&
  39        git add a init z &&
  40        git commit -m "super commit 1"
  41'
  42
  43test_expect_success 'setup - hide init subdirectory' '
  44        mv init .subrepo
  45'
  46
  47test_expect_success 'setup - add an example entry to .gitmodules' '
  48        GIT_CONFIG=.gitmodules \
  49        git config submodule.example.url git://example.com/init.git
  50'
  51
  52test_expect_success 'setup - repository to add submodules to' '
  53        git init addtest
  54'
  55
  56# The 'submodule add' tests need some repository to add as a submodule.
  57# The trash directory is a good one as any.
  58submodurl=$TRASH_DIRECTORY
  59
  60listbranches() {
  61        git for-each-ref --format='%(refname)' 'refs/heads/*'
  62}
  63
  64inspect() {
  65        dir=$1 &&
  66        dotdot="${2:-..}" &&
  67
  68        (
  69                cd "$dir" &&
  70                listbranches >"$dotdot/heads" &&
  71                { git symbolic-ref HEAD || :; } >"$dotdot/head" &&
  72                git update-index --refresh &&
  73                git diff-files --exit-code &&
  74                git clean -n -d -x >"$dotdot/untracked"
  75        )
  76}
  77
  78test_expect_success 'submodule add' '
  79        echo "refs/heads/master" >expect &&
  80        >empty &&
  81
  82        (
  83                cd addtest &&
  84                git submodule add "$submodurl" submod &&
  85                git submodule init
  86        ) &&
  87
  88        rm -f heads head untracked &&
  89        inspect addtest/submod ../.. &&
  90        test_cmp expect heads &&
  91        test_cmp expect head &&
  92        test_cmp empty untracked
  93'
  94
  95test_expect_success 'submodule add --branch' '
  96        echo "refs/heads/initial" >expect-head &&
  97        cat <<-\EOF >expect-heads &&
  98        refs/heads/initial
  99        refs/heads/master
 100        EOF
 101        >empty &&
 102
 103        (
 104                cd addtest &&
 105                git submodule add -b initial "$submodurl" submod-branch &&
 106                git submodule init
 107        ) &&
 108
 109        rm -f heads head untracked &&
 110        inspect addtest/submod-branch ../.. &&
 111        test_cmp expect-heads heads &&
 112        test_cmp expect-head head &&
 113        test_cmp empty untracked
 114'
 115
 116test_expect_success 'submodule add with ./ in path' '
 117        echo "refs/heads/master" >expect &&
 118        >empty &&
 119
 120        (
 121                cd addtest &&
 122                git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
 123                git submodule init
 124        ) &&
 125
 126        rm -f heads head untracked &&
 127        inspect addtest/dotsubmod/frotz ../../.. &&
 128        test_cmp expect heads &&
 129        test_cmp expect head &&
 130        test_cmp empty untracked
 131'
 132
 133test_expect_success 'submodule add with // in path' '
 134        echo "refs/heads/master" >expect &&
 135        >empty &&
 136
 137        (
 138                cd addtest &&
 139                git submodule add "$submodurl" slashslashsubmod///frotz// &&
 140                git submodule init
 141        ) &&
 142
 143        rm -f heads head untracked &&
 144        inspect addtest/slashslashsubmod/frotz ../../.. &&
 145        test_cmp expect heads &&
 146        test_cmp expect head &&
 147        test_cmp empty untracked
 148'
 149
 150test_expect_success 'submodule add with /.. in path' '
 151        echo "refs/heads/master" >expect &&
 152        >empty &&
 153
 154        (
 155                cd addtest &&
 156                git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
 157                git submodule init
 158        ) &&
 159
 160        rm -f heads head untracked &&
 161        inspect addtest/realsubmod ../.. &&
 162        test_cmp expect heads &&
 163        test_cmp expect head &&
 164        test_cmp empty untracked
 165'
 166
 167test_expect_success 'submodule add with ./, /.. and // in path' '
 168        echo "refs/heads/master" >expect &&
 169        >empty &&
 170
 171        (
 172                cd addtest &&
 173                git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
 174                git submodule init
 175        ) &&
 176
 177        rm -f heads head untracked &&
 178        inspect addtest/realsubmod2 ../.. &&
 179        test_cmp expect heads &&
 180        test_cmp expect head &&
 181        test_cmp empty untracked
 182'
 183
 184test_expect_success 'status should fail for unmapped paths' '
 185        if git submodule status
 186        then
 187                echo "[OOPS] submodule status succeeded"
 188                false
 189        elif ! GIT_CONFIG=.gitmodules git config submodule.example.path init
 190        then
 191                echo "[OOPS] git config failed to update .gitmodules"
 192                false
 193        fi
 194'
 195
 196test_expect_success 'status should only print one line' '
 197        lines=$(git submodule status | wc -l) &&
 198        test $lines = 1
 199'
 200
 201test_expect_success 'status should initially be "missing"' '
 202        git submodule status | grep "^-$rev1"
 203'
 204
 205test_expect_success 'init should register submodule url in .git/config' '
 206        git submodule init &&
 207        url=$(git config submodule.example.url) &&
 208        if test "$url" != "git://example.com/init.git"
 209        then
 210                echo "[OOPS] init succeeded but submodule url is wrong"
 211                false
 212        elif test_must_fail git config submodule.example.url ./.subrepo
 213        then
 214                echo "[OOPS] init succeeded but update of url failed"
 215                false
 216        fi
 217'
 218
 219test_expect_success 'update should fail when path is used by a file' '
 220        echo "hello" >init &&
 221        if git submodule update
 222        then
 223                echo "[OOPS] update should have failed"
 224                false
 225        elif test "$(cat init)" != "hello"
 226        then
 227                echo "[OOPS] update failed but init file was molested"
 228                false
 229        else
 230                rm init
 231        fi
 232'
 233
 234test_expect_success 'update should fail when path is used by a nonempty directory' '
 235        mkdir init &&
 236        echo "hello" >init/a &&
 237        if git submodule update
 238        then
 239                echo "[OOPS] update should have failed"
 240                false
 241        elif test "$(cat init/a)" != "hello"
 242        then
 243                echo "[OOPS] update failed but init/a was molested"
 244                false
 245        else
 246                rm init/a
 247        fi
 248'
 249
 250test_expect_success 'update should work when path is an empty dir' '
 251        rm -rf init &&
 252        mkdir init &&
 253        git submodule update &&
 254        head=$(cd init && git rev-parse HEAD) &&
 255        if test -z "$head"
 256        then
 257                echo "[OOPS] Failed to obtain submodule head"
 258                false
 259        elif test "$head" != "$rev1"
 260        then
 261                echo "[OOPS] Submodule head is $head but should have been $rev1"
 262                false
 263        fi
 264'
 265
 266test_expect_success 'status should be "up-to-date" after update' '
 267        git submodule status | grep "^ $rev1"
 268'
 269
 270test_expect_success 'status should be "modified" after submodule commit' '
 271        cd init &&
 272        echo b >b &&
 273        git add b &&
 274        git commit -m "submodule commit 2" &&
 275        rev2=$(git rev-parse HEAD) &&
 276        cd .. &&
 277        if test -z "$rev2"
 278        then
 279                echo "[OOPS] submodule git rev-parse returned nothing"
 280                false
 281        fi &&
 282        git submodule status | grep "^+$rev2"
 283'
 284
 285test_expect_success 'the --cached sha1 should be rev1' '
 286        git submodule --cached status | grep "^+$rev1"
 287'
 288
 289test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
 290        git diff | grep "^+Subproject commit $rev2"
 291'
 292
 293test_expect_success 'update should checkout rev1' '
 294        git submodule update init &&
 295        head=$(cd init && git rev-parse HEAD) &&
 296        if test -z "$head"
 297        then
 298                echo "[OOPS] submodule git rev-parse returned nothing"
 299                false
 300        elif test "$head" != "$rev1"
 301        then
 302                echo "[OOPS] init did not checkout correct head"
 303                false
 304        fi
 305'
 306
 307test_expect_success 'status should be "up-to-date" after update' '
 308        git submodule status | grep "^ $rev1"
 309'
 310
 311test_expect_success 'checkout superproject with subproject already present' '
 312        git checkout initial &&
 313        git checkout master
 314'
 315
 316test_expect_success 'apply submodule diff' '
 317        git branch second &&
 318        (
 319                cd init &&
 320                echo s >s &&
 321                git add s &&
 322                git commit -m "change subproject"
 323        ) &&
 324        git update-index --add init &&
 325        git commit -m "change init" &&
 326        git format-patch -1 --stdout >P.diff &&
 327        git checkout second &&
 328        git apply --index P.diff &&
 329        D=$(git diff --cached master) &&
 330        test -z "$D"
 331'
 332
 333test_expect_success 'update --init' '
 334
 335        mv init init2 &&
 336        git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
 337        git config --remove-section submodule.example
 338        git submodule update init > update.out &&
 339        grep "not initialized" update.out &&
 340        test ! -d init/.git &&
 341        git submodule update --init init &&
 342        test -d init/.git
 343
 344'
 345
 346test_expect_success 'do not add files from a submodule' '
 347
 348        git reset --hard &&
 349        test_must_fail git add init/a
 350
 351'
 352
 353test_expect_success 'gracefully add submodule with a trailing slash' '
 354
 355        git reset --hard &&
 356        git commit -m "commit subproject" init &&
 357        (cd init &&
 358         echo b > a) &&
 359        git add init/ &&
 360        git diff --exit-code --cached init &&
 361        commit=$(cd init &&
 362         git commit -m update a >/dev/null &&
 363         git rev-parse HEAD) &&
 364        git add init/ &&
 365        test_must_fail git diff --exit-code --cached init &&
 366        test $commit = $(git ls-files --stage |
 367                sed -n "s/^160000 \([^ ]*\).*/\1/p")
 368
 369'
 370
 371test_expect_success 'ls-files gracefully handles trailing slash' '
 372
 373        test "init" = "$(git ls-files init/)"
 374
 375'
 376
 377test_expect_success 'moving to a commit without submodule does not leave empty dir' '
 378        rm -rf init &&
 379        mkdir init &&
 380        git reset --hard &&
 381        git checkout initial &&
 382        test ! -d init &&
 383        git checkout second
 384'
 385
 386test_expect_success 'submodule <invalid-path> warns' '
 387
 388        git submodule no-such-submodule 2> output.err &&
 389        grep "^error: .*no-such-submodule" output.err
 390
 391'
 392
 393test_expect_success 'add submodules without specifying an explicit path' '
 394        mkdir repo &&
 395        cd repo &&
 396        git init &&
 397        echo r >r &&
 398        git add r &&
 399        git commit -m "repo commit 1" &&
 400        cd .. &&
 401        git clone --bare repo/ bare.git &&
 402        cd addtest &&
 403        git submodule add "$submodurl/repo" &&
 404        git config -f .gitmodules submodule.repo.path repo &&
 405        git submodule add "$submodurl/bare.git" &&
 406        git config -f .gitmodules submodule.bare.path bare
 407'
 408
 409test_done