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