t / t5703-upload-pack-ref-in-want.shon commit Merge branch 'tb/banned-vsprintf-namefix' (37801f0)
   1#!/bin/sh
   2
   3test_description='upload-pack ref-in-want'
   4
   5. ./test-lib.sh
   6
   7get_actual_refs () {
   8        sed -n -e '/wanted-refs/,/0001/{
   9                /wanted-refs/d
  10                /0001/d
  11                p
  12                }' <out | test-tool pkt-line unpack >actual_refs
  13}
  14
  15get_actual_commits () {
  16        sed -n -e '/packfile/,/0000/{
  17                /packfile/d
  18                p
  19                }' <out | test-tool pkt-line unpack-sideband >o.pack &&
  20        git index-pack o.pack &&
  21        git verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits
  22}
  23
  24check_output () {
  25        get_actual_refs &&
  26        test_cmp expected_refs actual_refs &&
  27        get_actual_commits &&
  28        test_cmp expected_commits actual_commits
  29}
  30
  31# c(o/foo) d(o/bar)
  32#        \ /
  33#         b   e(baz)  f(master)
  34#          \__  |  __/
  35#             \ | /
  36#               a
  37test_expect_success 'setup repository' '
  38        test_commit a &&
  39        git checkout -b o/foo &&
  40        test_commit b &&
  41        test_commit c &&
  42        git checkout -b o/bar b &&
  43        test_commit d &&
  44        git checkout -b baz a &&
  45        test_commit e &&
  46        git checkout master &&
  47        test_commit f
  48'
  49
  50test_expect_success 'config controls ref-in-want advertisement' '
  51        test-tool serve-v2 --advertise-capabilities >out &&
  52        ! grep -a ref-in-want out &&
  53
  54        git config uploadpack.allowRefInWant false &&
  55        test-tool serve-v2 --advertise-capabilities >out &&
  56        ! grep -a ref-in-want out &&
  57
  58        git config uploadpack.allowRefInWant true &&
  59        test-tool serve-v2 --advertise-capabilities >out &&
  60        grep -a ref-in-want out
  61'
  62
  63test_expect_success 'invalid want-ref line' '
  64        test-tool pkt-line pack >in <<-EOF &&
  65        command=fetch
  66        0001
  67        no-progress
  68        want-ref refs/heads/non-existent
  69        done
  70        0000
  71        EOF
  72
  73        test_must_fail test-tool serve-v2 --stateless-rpc 2>out <in &&
  74        grep "unknown ref" out
  75'
  76
  77test_expect_success 'basic want-ref' '
  78        cat >expected_refs <<-EOF &&
  79        $(git rev-parse f) refs/heads/master
  80        EOF
  81        git rev-parse f | sort >expected_commits &&
  82
  83        test-tool pkt-line pack >in <<-EOF &&
  84        command=fetch
  85        0001
  86        no-progress
  87        want-ref refs/heads/master
  88        have $(git rev-parse a)
  89        done
  90        0000
  91        EOF
  92
  93        test-tool serve-v2 --stateless-rpc >out <in &&
  94        check_output
  95'
  96
  97test_expect_success 'multiple want-ref lines' '
  98        cat >expected_refs <<-EOF &&
  99        $(git rev-parse c) refs/heads/o/foo
 100        $(git rev-parse d) refs/heads/o/bar
 101        EOF
 102        git rev-parse c d | sort >expected_commits &&
 103
 104        test-tool pkt-line pack >in <<-EOF &&
 105        command=fetch
 106        0001
 107        no-progress
 108        want-ref refs/heads/o/foo
 109        want-ref refs/heads/o/bar
 110        have $(git rev-parse b)
 111        done
 112        0000
 113        EOF
 114
 115        test-tool serve-v2 --stateless-rpc >out <in &&
 116        check_output
 117'
 118
 119test_expect_success 'mix want and want-ref' '
 120        cat >expected_refs <<-EOF &&
 121        $(git rev-parse f) refs/heads/master
 122        EOF
 123        git rev-parse e f | sort >expected_commits &&
 124
 125        test-tool pkt-line pack >in <<-EOF &&
 126        command=fetch
 127        0001
 128        no-progress
 129        want-ref refs/heads/master
 130        want $(git rev-parse e)
 131        have $(git rev-parse a)
 132        done
 133        0000
 134        EOF
 135
 136        test-tool serve-v2 --stateless-rpc >out <in &&
 137        check_output
 138'
 139
 140test_expect_success 'want-ref with ref we already have commit for' '
 141        cat >expected_refs <<-EOF &&
 142        $(git rev-parse c) refs/heads/o/foo
 143        EOF
 144        >expected_commits &&
 145
 146        test-tool pkt-line pack >in <<-EOF &&
 147        command=fetch
 148        0001
 149        no-progress
 150        want-ref refs/heads/o/foo
 151        have $(git rev-parse c)
 152        done
 153        0000
 154        EOF
 155
 156        test-tool serve-v2 --stateless-rpc >out <in &&
 157        check_output
 158'
 159
 160REPO="$(pwd)/repo"
 161LOCAL_PRISTINE="$(pwd)/local_pristine"
 162
 163# $REPO
 164# c(o/foo) d(o/bar)
 165#        \ /
 166#         b   e(baz)  f(master)
 167#          \__  |  __/
 168#             \ | /
 169#               a
 170#
 171# $LOCAL_PRISTINE
 172#               s32(side)
 173#               |
 174#               .
 175#               .
 176#               |
 177#               a(master)
 178test_expect_success 'setup repos for fetching with ref-in-want tests' '
 179        (
 180                git init "$REPO" &&
 181                cd "$REPO" &&
 182                test_commit a &&
 183
 184                # Local repo with many commits (so that negotiation will take
 185                # more than 1 request/response pair)
 186                rm -rf "$LOCAL_PRISTINE" &&
 187                git clone "file://$REPO" "$LOCAL_PRISTINE" &&
 188                cd "$LOCAL_PRISTINE" &&
 189                git checkout -b side &&
 190                test_commit_bulk --id=s 33 &&
 191
 192                # Add novel commits to upstream
 193                git checkout master &&
 194                cd "$REPO" &&
 195                git checkout -b o/foo &&
 196                test_commit b &&
 197                test_commit c &&
 198                git checkout -b o/bar b &&
 199                test_commit d &&
 200                git checkout -b baz a &&
 201                test_commit e &&
 202                git checkout master &&
 203                test_commit f
 204        ) &&
 205        git -C "$REPO" config uploadpack.allowRefInWant true &&
 206        git -C "$LOCAL_PRISTINE" config protocol.version 2
 207'
 208
 209test_expect_success 'fetching with exact OID' '
 210        test_when_finished "rm -f log" &&
 211
 212        rm -rf local &&
 213        cp -r "$LOCAL_PRISTINE" local &&
 214        GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin \
 215                $(git -C "$REPO" rev-parse d):refs/heads/actual &&
 216
 217        git -C "$REPO" rev-parse "d" >expected &&
 218        git -C local rev-parse refs/heads/actual >actual &&
 219        test_cmp expected actual &&
 220        grep "want $(git -C "$REPO" rev-parse d)" log
 221'
 222
 223test_expect_success 'fetching multiple refs' '
 224        test_when_finished "rm -f log" &&
 225
 226        rm -rf local &&
 227        cp -r "$LOCAL_PRISTINE" local &&
 228        GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin master baz &&
 229
 230        git -C "$REPO" rev-parse "master" "baz" >expected &&
 231        git -C local rev-parse refs/remotes/origin/master refs/remotes/origin/baz >actual &&
 232        test_cmp expected actual &&
 233        grep "want-ref refs/heads/master" log &&
 234        grep "want-ref refs/heads/baz" log
 235'
 236
 237test_expect_success 'fetching ref and exact OID' '
 238        test_when_finished "rm -f log" &&
 239
 240        rm -rf local &&
 241        cp -r "$LOCAL_PRISTINE" local &&
 242        GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin \
 243                master $(git -C "$REPO" rev-parse b):refs/heads/actual &&
 244
 245        git -C "$REPO" rev-parse "master" "b" >expected &&
 246        git -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&
 247        test_cmp expected actual &&
 248        grep "want $(git -C "$REPO" rev-parse b)" log &&
 249        grep "want-ref refs/heads/master" log
 250'
 251
 252test_expect_success 'fetching with wildcard that does not match any refs' '
 253        test_when_finished "rm -f log" &&
 254
 255        rm -rf local &&
 256        cp -r "$LOCAL_PRISTINE" local &&
 257        git -C local fetch origin refs/heads/none*:refs/heads/* >out &&
 258        test_must_be_empty out
 259'
 260
 261test_expect_success 'fetching with wildcard that matches multiple refs' '
 262        test_when_finished "rm -f log" &&
 263
 264        rm -rf local &&
 265        cp -r "$LOCAL_PRISTINE" local &&
 266        GIT_TRACE_PACKET="$(pwd)/log" git -C local fetch origin refs/heads/o*:refs/heads/o* &&
 267
 268        git -C "$REPO" rev-parse "o/foo" "o/bar" >expected &&
 269        git -C local rev-parse "o/foo" "o/bar" >actual &&
 270        test_cmp expected actual &&
 271        grep "want-ref refs/heads/o/foo" log &&
 272        grep "want-ref refs/heads/o/bar" log
 273'
 274
 275. "$TEST_DIRECTORY"/lib-httpd.sh
 276start_httpd
 277
 278REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
 279LOCAL_PRISTINE="$(pwd)/local_pristine"
 280
 281test_expect_success 'setup repos for change-while-negotiating test' '
 282        (
 283                git init "$REPO" &&
 284                cd "$REPO" &&
 285                >.git/git-daemon-export-ok &&
 286                test_commit m1 &&
 287                git tag -d m1 &&
 288
 289                # Local repo with many commits (so that negotiation will take
 290                # more than 1 request/response pair)
 291                rm -rf "$LOCAL_PRISTINE" &&
 292                git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" &&
 293                cd "$LOCAL_PRISTINE" &&
 294                git checkout -b side &&
 295                test_commit_bulk --id=s 33 &&
 296
 297                # Add novel commits to upstream
 298                git checkout master &&
 299                cd "$REPO" &&
 300                test_commit m2 &&
 301                test_commit m3 &&
 302                git tag -d m2 m3
 303        ) &&
 304        git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_sed/repo" &&
 305        git -C "$LOCAL_PRISTINE" config protocol.version 2
 306'
 307
 308inconsistency () {
 309        # Simulate that the server initially reports $2 as the ref
 310        # corresponding to $1, and after that, $1 as the ref corresponding to
 311        # $1. This corresponds to the real-life situation where the server's
 312        # repository appears to change during negotiation, for example, when
 313        # different servers in a load-balancing arrangement serve (stateless)
 314        # RPCs during a single negotiation.
 315        printf "s/%s/%s/" \
 316               $(git -C "$REPO" rev-parse $1 | tr -d "\n") \
 317               $(git -C "$REPO" rev-parse $2 | tr -d "\n") \
 318               >"$HTTPD_ROOT_PATH/one-time-sed"
 319}
 320
 321test_expect_success 'server is initially ahead - no ref in want' '
 322        git -C "$REPO" config uploadpack.allowRefInWant false &&
 323        rm -rf local &&
 324        cp -r "$LOCAL_PRISTINE" local &&
 325        inconsistency master 1234567890123456789012345678901234567890 &&
 326        test_must_fail git -C local fetch 2>err &&
 327        test_i18ngrep "fatal: remote error: upload-pack: not our ref" err
 328'
 329
 330test_expect_success 'server is initially ahead - ref in want' '
 331        git -C "$REPO" config uploadpack.allowRefInWant true &&
 332        rm -rf local &&
 333        cp -r "$LOCAL_PRISTINE" local &&
 334        inconsistency master 1234567890123456789012345678901234567890 &&
 335        git -C local fetch &&
 336
 337        git -C "$REPO" rev-parse --verify master >expected &&
 338        git -C local rev-parse --verify refs/remotes/origin/master >actual &&
 339        test_cmp expected actual
 340'
 341
 342test_expect_success 'server is initially behind - no ref in want' '
 343        git -C "$REPO" config uploadpack.allowRefInWant false &&
 344        rm -rf local &&
 345        cp -r "$LOCAL_PRISTINE" local &&
 346        inconsistency master "master^" &&
 347        git -C local fetch &&
 348
 349        git -C "$REPO" rev-parse --verify "master^" >expected &&
 350        git -C local rev-parse --verify refs/remotes/origin/master >actual &&
 351        test_cmp expected actual
 352'
 353
 354test_expect_success 'server is initially behind - ref in want' '
 355        git -C "$REPO" config uploadpack.allowRefInWant true &&
 356        rm -rf local &&
 357        cp -r "$LOCAL_PRISTINE" local &&
 358        inconsistency master "master^" &&
 359        git -C local fetch &&
 360
 361        git -C "$REPO" rev-parse --verify "master" >expected &&
 362        git -C local rev-parse --verify refs/remotes/origin/master >actual &&
 363        test_cmp expected actual
 364'
 365
 366test_expect_success 'server loses a ref - ref in want' '
 367        git -C "$REPO" config uploadpack.allowRefInWant true &&
 368        rm -rf local &&
 369        cp -r "$LOCAL_PRISTINE" local &&
 370        echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-sed" &&
 371        test_must_fail git -C local fetch 2>err &&
 372
 373        test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err
 374'
 375
 376# DO NOT add non-httpd-specific tests here, because the last part of this
 377# test script is only executed when httpd is available and enabled.
 378
 379test_done