t / t5400-send-pack.shon commit Merge branch 'nd/switch-and-restore' (3ff6af7)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6test_description='See why rewinding head breaks send-pack
   7
   8'
   9. ./test-lib.sh
  10
  11cnt=64
  12test_expect_success setup '
  13        test_tick &&
  14        mkdir mozart mozart/is &&
  15        echo "Commit #0" >mozart/is/pink &&
  16        git update-index --add mozart/is/pink &&
  17        tree=$(git write-tree) &&
  18        commit=$(echo "Commit #0" | git commit-tree $tree) &&
  19        zero=$commit &&
  20        parent=$zero &&
  21        i=0 &&
  22        while test $i -le $cnt
  23        do
  24            i=$(($i+1)) &&
  25            test_tick &&
  26            echo "Commit #$i" >mozart/is/pink &&
  27            git update-index --add mozart/is/pink &&
  28            tree=$(git write-tree) &&
  29            commit=$(echo "Commit #$i" | git commit-tree $tree -p $parent) &&
  30            git update-ref refs/tags/commit$i $commit &&
  31            parent=$commit || return 1
  32        done &&
  33        git update-ref HEAD "$commit" &&
  34        git clone ./. victim &&
  35        ( cd victim && git config receive.denyCurrentBranch warn && git log ) &&
  36        git update-ref HEAD "$zero" &&
  37        parent=$zero &&
  38        i=0 &&
  39        while test $i -le $cnt
  40        do
  41            i=$(($i+1)) &&
  42            test_tick &&
  43            echo "Rebase #$i" >mozart/is/pink &&
  44            git update-index --add mozart/is/pink &&
  45            tree=$(git write-tree) &&
  46            commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) &&
  47            git update-ref refs/tags/rebase$i $commit &&
  48            parent=$commit || return 1
  49        done &&
  50        git update-ref HEAD "$commit" &&
  51        echo Rebase &&
  52        git log'
  53
  54test_expect_success 'pack the source repository' '
  55        git repack -a -d &&
  56        git prune
  57'
  58
  59test_expect_success 'pack the destination repository' '
  60    (
  61        cd victim &&
  62        git repack -a -d &&
  63        git prune
  64    )
  65'
  66
  67test_expect_success 'refuse pushing rewound head without --force' '
  68        pushed_head=$(git rev-parse --verify master) &&
  69        victim_orig=$(cd victim && git rev-parse --verify master) &&
  70        test_must_fail git send-pack ./victim master &&
  71        victim_head=$(cd victim && git rev-parse --verify master) &&
  72        test "$victim_head" = "$victim_orig" &&
  73        # this should update
  74        git send-pack --force ./victim master &&
  75        victim_head=$(cd victim && git rev-parse --verify master) &&
  76        test "$victim_head" = "$pushed_head"
  77'
  78
  79test_expect_success 'push can be used to delete a ref' '
  80        ( cd victim && git branch extra master ) &&
  81        git send-pack ./victim :extra master &&
  82        ( cd victim &&
  83          test_must_fail git rev-parse --verify extra )
  84'
  85
  86test_expect_success 'refuse deleting push with denyDeletes' '
  87        (
  88            cd victim &&
  89            test_might_fail git branch -D extra &&
  90            git config receive.denyDeletes true &&
  91            git branch extra master
  92        ) &&
  93        test_must_fail git send-pack ./victim :extra master
  94'
  95
  96test_expect_success 'cannot override denyDeletes with git -c send-pack' '
  97        (
  98                cd victim &&
  99                test_might_fail git branch -D extra &&
 100                git config receive.denyDeletes true &&
 101                git branch extra master
 102        ) &&
 103        test_must_fail git -c receive.denyDeletes=false \
 104                                        send-pack ./victim :extra master
 105'
 106
 107test_expect_success 'override denyDeletes with git -c receive-pack' '
 108        (
 109                cd victim &&
 110                test_might_fail git branch -D extra &&
 111                git config receive.denyDeletes true &&
 112                git branch extra master
 113        ) &&
 114        git send-pack \
 115                --receive-pack="git -c receive.denyDeletes=false receive-pack" \
 116                ./victim :extra master
 117'
 118
 119test_expect_success 'denyNonFastforwards trumps --force' '
 120        (
 121            cd victim &&
 122            test_might_fail git branch -D extra &&
 123            git config receive.denyNonFastforwards true
 124        ) &&
 125        victim_orig=$(cd victim && git rev-parse --verify master) &&
 126        test_must_fail git send-pack --force ./victim master^:master &&
 127        victim_head=$(cd victim && git rev-parse --verify master) &&
 128        test "$victim_orig" = "$victim_head"
 129'
 130
 131test_expect_success 'send-pack --all sends all branches' '
 132        # make sure we have at least 2 branches with different
 133        # values, just to be thorough
 134        git branch other-branch HEAD^ &&
 135
 136        git init --bare all.git &&
 137        git send-pack --all all.git &&
 138        git for-each-ref refs/heads >expect &&
 139        git -C all.git for-each-ref refs/heads >actual &&
 140        test_cmp expect actual
 141'
 142
 143test_expect_success 'push --all excludes remote-tracking hierarchy' '
 144        mkdir parent &&
 145        (
 146            cd parent &&
 147            git init && : >file && git add file && git commit -m add
 148        ) &&
 149        git clone parent child &&
 150        (
 151            cd child && git push --all
 152        ) &&
 153        (
 154            cd parent &&
 155            test -z "$(git for-each-ref refs/remotes/origin)"
 156        )
 157'
 158
 159test_expect_success 'receive-pack runs auto-gc in remote repo' '
 160        rm -rf parent child &&
 161        git init parent &&
 162        (
 163            # Setup a repo with 2 packs
 164            cd parent &&
 165            echo "Some text" >file.txt &&
 166            git add . &&
 167            git commit -m "Initial commit" &&
 168            git repack -adl &&
 169            echo "Some more text" >>file.txt &&
 170            git commit -a -m "Second commit" &&
 171            git repack
 172        ) &&
 173        cp -R parent child &&
 174        (
 175            # Set the child to auto-pack if more than one pack exists
 176            cd child &&
 177            git config gc.autopacklimit 1 &&
 178            git config gc.autodetach false &&
 179            git branch test_auto_gc &&
 180            # And create a file that follows the temporary object naming
 181            # convention for the auto-gc to remove
 182            : >.git/objects/tmp_test_object &&
 183            test-tool chmtime =-1209601 .git/objects/tmp_test_object
 184        ) &&
 185        (
 186            cd parent &&
 187            echo "Even more text" >>file.txt &&
 188            git commit -a -m "Third commit" &&
 189            git send-pack ../child HEAD:refs/heads/test_auto_gc
 190        ) &&
 191        test ! -e child/.git/objects/tmp_test_object
 192'
 193
 194rewound_push_setup() {
 195        rm -rf parent child &&
 196        mkdir parent &&
 197        (
 198            cd parent &&
 199            git init &&
 200            echo one >file && git add file && git commit -m one &&
 201            git config receive.denyCurrentBranch warn &&
 202            echo two >file && git commit -a -m two
 203        ) &&
 204        git clone parent child &&
 205        (
 206            cd child && git reset --hard HEAD^
 207        )
 208}
 209
 210test_expect_success 'pushing explicit refspecs respects forcing' '
 211        rewound_push_setup &&
 212        parent_orig=$(cd parent && git rev-parse --verify master) &&
 213        (
 214            cd child &&
 215            test_must_fail git send-pack ../parent \
 216                refs/heads/master:refs/heads/master
 217        ) &&
 218        parent_head=$(cd parent && git rev-parse --verify master) &&
 219        test "$parent_orig" = "$parent_head" &&
 220        (
 221            cd child &&
 222            git send-pack ../parent \
 223                +refs/heads/master:refs/heads/master
 224        ) &&
 225        parent_head=$(cd parent && git rev-parse --verify master) &&
 226        child_head=$(cd child && git rev-parse --verify master) &&
 227        test "$parent_head" = "$child_head"
 228'
 229
 230test_expect_success 'pushing wildcard refspecs respects forcing' '
 231        rewound_push_setup &&
 232        parent_orig=$(cd parent && git rev-parse --verify master) &&
 233        (
 234            cd child &&
 235            test_must_fail git send-pack ../parent \
 236                "refs/heads/*:refs/heads/*"
 237        ) &&
 238        parent_head=$(cd parent && git rev-parse --verify master) &&
 239        test "$parent_orig" = "$parent_head" &&
 240        (
 241            cd child &&
 242            git send-pack ../parent \
 243                "+refs/heads/*:refs/heads/*"
 244        ) &&
 245        parent_head=$(cd parent && git rev-parse --verify master) &&
 246        child_head=$(cd child && git rev-parse --verify master) &&
 247        test "$parent_head" = "$child_head"
 248'
 249
 250test_expect_success 'deny pushing to delete current branch' '
 251        rewound_push_setup &&
 252        (
 253            cd child &&
 254            test_must_fail git send-pack ../parent :refs/heads/master 2>errs
 255        )
 256'
 257
 258extract_ref_advertisement () {
 259        perl -lne '
 260                # \\ is there to skip capabilities after \0
 261                /push< ([^\\]+)/ or next;
 262                exit 0 if $1 eq "0000";
 263                print $1;
 264        '
 265}
 266
 267test_expect_success 'receive-pack de-dupes .have lines' '
 268        git init shared &&
 269        git -C shared commit --allow-empty -m both &&
 270        git clone -s shared fork &&
 271        (
 272                cd shared &&
 273                git checkout -b only-shared &&
 274                git commit --allow-empty -m only-shared &&
 275                git update-ref refs/heads/foo HEAD
 276        ) &&
 277
 278        # Notable things in this expectation:
 279        #  - local refs are not de-duped
 280        #  - .have does not duplicate locals
 281        #  - .have does not duplicate itself
 282        local=$(git -C fork rev-parse HEAD) &&
 283        shared=$(git -C shared rev-parse only-shared) &&
 284        cat >expect <<-EOF &&
 285        $local refs/heads/master
 286        $local refs/remotes/origin/HEAD
 287        $local refs/remotes/origin/master
 288        $shared .have
 289        EOF
 290
 291        GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION= \
 292            git push \
 293                --receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \
 294                fork HEAD:foo &&
 295        extract_ref_advertisement <trace >refs &&
 296        test_cmp expect refs
 297'
 298
 299test_done