t / t1404-update-ref-errors.shon commit Merge branch 'ds/commit-graph-on-fetch' (5a53509)
   1#!/bin/sh
   2
   3test_description='Test git update-ref error handling'
   4. ./test-lib.sh
   5
   6# Create some references, perhaps run pack-refs --all, then try to
   7# create some more references. Ensure that the second creation fails
   8# with the correct error message.
   9# Usage: test_update_rejected <before> <pack> <create> <error>
  10#   <before> is a ws-separated list of refs to create before the test
  11#   <pack> (true or false) tells whether to pack the refs before the test
  12#   <create> is a list of variables to attempt creating
  13#   <error> is a string to look for in the stderr of update-ref.
  14# All references are created in the namespace specified by the current
  15# value of $prefix.
  16test_update_rejected () {
  17        before="$1" &&
  18        pack="$2" &&
  19        create="$3" &&
  20        error="$4" &&
  21        printf "create $prefix/%s $C\n" $before |
  22        git update-ref --stdin &&
  23        git for-each-ref $prefix >unchanged &&
  24        if $pack
  25        then
  26                git pack-refs --all
  27        fi &&
  28        printf "create $prefix/%s $C\n" $create >input &&
  29        test_must_fail git update-ref --stdin <input 2>output.err &&
  30        test_i18ngrep -F "$error" output.err &&
  31        git for-each-ref $prefix >actual &&
  32        test_cmp unchanged actual
  33}
  34
  35# Test adding and deleting D/F-conflicting references in a single
  36# transaction.
  37df_test() {
  38        prefix="$1"
  39        pack=: symadd=false symdel=false add_del=false addref= delref=
  40        shift
  41        while test $# -gt 0
  42        do
  43                case "$1" in
  44                --pack)
  45                        pack="git pack-refs --all"
  46                        shift
  47                        ;;
  48                --sym-add)
  49                        # Perform the add via a symbolic reference
  50                        symadd=true
  51                        shift
  52                        ;;
  53                --sym-del)
  54                        # Perform the del via a symbolic reference
  55                        symdel=true
  56                        shift
  57                        ;;
  58                --del-add)
  59                        # Delete first reference then add second
  60                        add_del=false
  61                        delref="$prefix/r/$2"
  62                        addref="$prefix/r/$3"
  63                        shift 3
  64                        ;;
  65                --add-del)
  66                        # Add first reference then delete second
  67                        add_del=true
  68                        addref="$prefix/r/$2"
  69                        delref="$prefix/r/$3"
  70                        shift 3
  71                        ;;
  72                *)
  73                        echo 1>&2 "Extra args to df_test: $*"
  74                        return 1
  75                        ;;
  76                esac
  77        done
  78        git update-ref "$delref" $C &&
  79        if $symadd
  80        then
  81                addname="$prefix/s/symadd" &&
  82                git symbolic-ref "$addname" "$addref"
  83        else
  84                addname="$addref"
  85        fi &&
  86        if $symdel
  87        then
  88                delname="$prefix/s/symdel" &&
  89                git symbolic-ref "$delname" "$delref"
  90        else
  91                delname="$delref"
  92        fi &&
  93        cat >expected-err <<-EOF &&
  94        fatal: cannot lock ref $SQ$addname$SQ: $SQ$delref$SQ exists; cannot create $SQ$addref$SQ
  95        EOF
  96        $pack &&
  97        if $add_del
  98        then
  99                printf "%s\n" "create $addname $D" "delete $delname"
 100        else
 101                printf "%s\n" "delete $delname" "create $addname $D"
 102        fi >commands &&
 103        test_must_fail git update-ref --stdin <commands 2>output.err &&
 104        test_i18ncmp expected-err output.err &&
 105        printf "%s\n" "$C $delref" >expected-refs &&
 106        git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
 107        test_cmp expected-refs actual-refs
 108}
 109
 110test_expect_success 'setup' '
 111
 112        git commit --allow-empty -m Initial &&
 113        C=$(git rev-parse HEAD) &&
 114        git commit --allow-empty -m Second &&
 115        D=$(git rev-parse HEAD) &&
 116        git commit --allow-empty -m Third &&
 117        E=$(git rev-parse HEAD)
 118'
 119
 120test_expect_success 'existing loose ref is a simple prefix of new' '
 121
 122        prefix=refs/1l &&
 123        test_update_rejected "a c e" false "b c/x d" \
 124                "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
 125
 126'
 127
 128test_expect_success 'existing packed ref is a simple prefix of new' '
 129
 130        prefix=refs/1p &&
 131        test_update_rejected "a c e" true "b c/x d" \
 132                "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
 133
 134'
 135
 136test_expect_success 'existing loose ref is a deeper prefix of new' '
 137
 138        prefix=refs/2l &&
 139        test_update_rejected "a c e" false "b c/x/y d" \
 140                "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
 141
 142'
 143
 144test_expect_success 'existing packed ref is a deeper prefix of new' '
 145
 146        prefix=refs/2p &&
 147        test_update_rejected "a c e" true "b c/x/y d" \
 148                "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
 149
 150'
 151
 152test_expect_success 'new ref is a simple prefix of existing loose' '
 153
 154        prefix=refs/3l &&
 155        test_update_rejected "a c/x e" false "b c d" \
 156                "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
 157
 158'
 159
 160test_expect_success 'new ref is a simple prefix of existing packed' '
 161
 162        prefix=refs/3p &&
 163        test_update_rejected "a c/x e" true "b c d" \
 164                "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
 165
 166'
 167
 168test_expect_success 'new ref is a deeper prefix of existing loose' '
 169
 170        prefix=refs/4l &&
 171        test_update_rejected "a c/x/y e" false "b c d" \
 172                "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
 173
 174'
 175
 176test_expect_success 'new ref is a deeper prefix of existing packed' '
 177
 178        prefix=refs/4p &&
 179        test_update_rejected "a c/x/y e" true "b c d" \
 180                "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
 181
 182'
 183
 184test_expect_success 'one new ref is a simple prefix of another' '
 185
 186        prefix=refs/5 &&
 187        test_update_rejected "a e" false "b c c/x d" \
 188                "cannot process $SQ$prefix/c$SQ and $SQ$prefix/c/x$SQ at the same time"
 189
 190'
 191
 192test_expect_success 'empty directory should not fool rev-parse' '
 193        prefix=refs/e-rev-parse &&
 194        git update-ref $prefix/foo $C &&
 195        git pack-refs --all &&
 196        mkdir -p .git/$prefix/foo/bar/baz &&
 197        echo "$C" >expected &&
 198        git rev-parse $prefix/foo >actual &&
 199        test_cmp expected actual
 200'
 201
 202test_expect_success 'empty directory should not fool for-each-ref' '
 203        prefix=refs/e-for-each-ref &&
 204        git update-ref $prefix/foo $C &&
 205        git for-each-ref $prefix >expected &&
 206        git pack-refs --all &&
 207        mkdir -p .git/$prefix/foo/bar/baz &&
 208        git for-each-ref $prefix >actual &&
 209        test_cmp expected actual
 210'
 211
 212test_expect_success 'empty directory should not fool create' '
 213        prefix=refs/e-create &&
 214        mkdir -p .git/$prefix/foo/bar/baz &&
 215        printf "create %s $C\n" $prefix/foo |
 216        git update-ref --stdin
 217'
 218
 219test_expect_success 'empty directory should not fool verify' '
 220        prefix=refs/e-verify &&
 221        git update-ref $prefix/foo $C &&
 222        git pack-refs --all &&
 223        mkdir -p .git/$prefix/foo/bar/baz &&
 224        printf "verify %s $C\n" $prefix/foo |
 225        git update-ref --stdin
 226'
 227
 228test_expect_success 'empty directory should not fool 1-arg update' '
 229        prefix=refs/e-update-1 &&
 230        git update-ref $prefix/foo $C &&
 231        git pack-refs --all &&
 232        mkdir -p .git/$prefix/foo/bar/baz &&
 233        printf "update %s $D\n" $prefix/foo |
 234        git update-ref --stdin
 235'
 236
 237test_expect_success 'empty directory should not fool 2-arg update' '
 238        prefix=refs/e-update-2 &&
 239        git update-ref $prefix/foo $C &&
 240        git pack-refs --all &&
 241        mkdir -p .git/$prefix/foo/bar/baz &&
 242        printf "update %s $D $C\n" $prefix/foo |
 243        git update-ref --stdin
 244'
 245
 246test_expect_success 'empty directory should not fool 0-arg delete' '
 247        prefix=refs/e-delete-0 &&
 248        git update-ref $prefix/foo $C &&
 249        git pack-refs --all &&
 250        mkdir -p .git/$prefix/foo/bar/baz &&
 251        printf "delete %s\n" $prefix/foo |
 252        git update-ref --stdin
 253'
 254
 255test_expect_success 'empty directory should not fool 1-arg delete' '
 256        prefix=refs/e-delete-1 &&
 257        git update-ref $prefix/foo $C &&
 258        git pack-refs --all &&
 259        mkdir -p .git/$prefix/foo/bar/baz &&
 260        printf "delete %s $C\n" $prefix/foo |
 261        git update-ref --stdin
 262'
 263
 264test_expect_success 'D/F conflict prevents add long + delete short' '
 265        df_test refs/df-al-ds --add-del foo/bar foo
 266'
 267
 268test_expect_success 'D/F conflict prevents add short + delete long' '
 269        df_test refs/df-as-dl --add-del foo foo/bar
 270'
 271
 272test_expect_success 'D/F conflict prevents delete long + add short' '
 273        df_test refs/df-dl-as --del-add foo/bar foo
 274'
 275
 276test_expect_success 'D/F conflict prevents delete short + add long' '
 277        df_test refs/df-ds-al --del-add foo foo/bar
 278'
 279
 280test_expect_success 'D/F conflict prevents add long + delete short packed' '
 281        df_test refs/df-al-dsp --pack --add-del foo/bar foo
 282'
 283
 284test_expect_success 'D/F conflict prevents add short + delete long packed' '
 285        df_test refs/df-as-dlp --pack --add-del foo foo/bar
 286'
 287
 288test_expect_success 'D/F conflict prevents delete long packed + add short' '
 289        df_test refs/df-dlp-as --pack --del-add foo/bar foo
 290'
 291
 292test_expect_success 'D/F conflict prevents delete short packed + add long' '
 293        df_test refs/df-dsp-al --pack --del-add foo foo/bar
 294'
 295
 296# Try some combinations involving symbolic refs...
 297
 298test_expect_success 'D/F conflict prevents indirect add long + delete short' '
 299        df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
 300'
 301
 302test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' '
 303        df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
 304'
 305
 306test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' '
 307        df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
 308'
 309
 310test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' '
 311        df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
 312'
 313
 314test_expect_success 'D/F conflict prevents indirect add long + delete short packed' '
 315        df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
 316'
 317
 318test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' '
 319        df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
 320'
 321
 322test_expect_success 'D/F conflict prevents add long + indirect delete short packed' '
 323        df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
 324'
 325
 326test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' '
 327        df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
 328'
 329
 330# Test various errors when reading the old values of references...
 331
 332test_expect_success 'missing old value blocks update' '
 333        prefix=refs/missing-update &&
 334        cat >expected <<-EOF &&
 335        fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
 336        EOF
 337        printf "%s\n" "update $prefix/foo $E $D" |
 338        test_must_fail git update-ref --stdin 2>output.err &&
 339        test_cmp expected output.err
 340'
 341
 342test_expect_success 'incorrect old value blocks update' '
 343        prefix=refs/incorrect-update &&
 344        git update-ref $prefix/foo $C &&
 345        cat >expected <<-EOF &&
 346        fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
 347        EOF
 348        printf "%s\n" "update $prefix/foo $E $D" |
 349        test_must_fail git update-ref --stdin 2>output.err &&
 350        test_cmp expected output.err
 351'
 352
 353test_expect_success 'existing old value blocks create' '
 354        prefix=refs/existing-create &&
 355        git update-ref $prefix/foo $C &&
 356        cat >expected <<-EOF &&
 357        fatal: cannot lock ref $SQ$prefix/foo$SQ: reference already exists
 358        EOF
 359        printf "%s\n" "create $prefix/foo $E" |
 360        test_must_fail git update-ref --stdin 2>output.err &&
 361        test_cmp expected output.err
 362'
 363
 364test_expect_success 'incorrect old value blocks delete' '
 365        prefix=refs/incorrect-delete &&
 366        git update-ref $prefix/foo $C &&
 367        cat >expected <<-EOF &&
 368        fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
 369        EOF
 370        printf "%s\n" "delete $prefix/foo $D" |
 371        test_must_fail git update-ref --stdin 2>output.err &&
 372        test_cmp expected output.err
 373'
 374
 375test_expect_success 'missing old value blocks indirect update' '
 376        prefix=refs/missing-indirect-update &&
 377        git symbolic-ref $prefix/symref $prefix/foo &&
 378        cat >expected <<-EOF &&
 379        fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
 380        EOF
 381        printf "%s\n" "update $prefix/symref $E $D" |
 382        test_must_fail git update-ref --stdin 2>output.err &&
 383        test_cmp expected output.err
 384'
 385
 386test_expect_success 'incorrect old value blocks indirect update' '
 387        prefix=refs/incorrect-indirect-update &&
 388        git symbolic-ref $prefix/symref $prefix/foo &&
 389        git update-ref $prefix/foo $C &&
 390        cat >expected <<-EOF &&
 391        fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
 392        EOF
 393        printf "%s\n" "update $prefix/symref $E $D" |
 394        test_must_fail git update-ref --stdin 2>output.err &&
 395        test_cmp expected output.err
 396'
 397
 398test_expect_success 'existing old value blocks indirect create' '
 399        prefix=refs/existing-indirect-create &&
 400        git symbolic-ref $prefix/symref $prefix/foo &&
 401        git update-ref $prefix/foo $C &&
 402        cat >expected <<-EOF &&
 403        fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
 404        EOF
 405        printf "%s\n" "create $prefix/symref $E" |
 406        test_must_fail git update-ref --stdin 2>output.err &&
 407        test_cmp expected output.err
 408'
 409
 410test_expect_success 'incorrect old value blocks indirect delete' '
 411        prefix=refs/incorrect-indirect-delete &&
 412        git symbolic-ref $prefix/symref $prefix/foo &&
 413        git update-ref $prefix/foo $C &&
 414        cat >expected <<-EOF &&
 415        fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
 416        EOF
 417        printf "%s\n" "delete $prefix/symref $D" |
 418        test_must_fail git update-ref --stdin 2>output.err &&
 419        test_cmp expected output.err
 420'
 421
 422test_expect_success 'missing old value blocks indirect no-deref update' '
 423        prefix=refs/missing-noderef-update &&
 424        git symbolic-ref $prefix/symref $prefix/foo &&
 425        cat >expected <<-EOF &&
 426        fatal: cannot lock ref $SQ$prefix/symref$SQ: reference is missing but expected $D
 427        EOF
 428        printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
 429        test_must_fail git update-ref --stdin 2>output.err &&
 430        test_cmp expected output.err
 431'
 432
 433test_expect_success 'incorrect old value blocks indirect no-deref update' '
 434        prefix=refs/incorrect-noderef-update &&
 435        git symbolic-ref $prefix/symref $prefix/foo &&
 436        git update-ref $prefix/foo $C &&
 437        cat >expected <<-EOF &&
 438        fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
 439        EOF
 440        printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
 441        test_must_fail git update-ref --stdin 2>output.err &&
 442        test_cmp expected output.err
 443'
 444
 445test_expect_success 'existing old value blocks indirect no-deref create' '
 446        prefix=refs/existing-noderef-create &&
 447        git symbolic-ref $prefix/symref $prefix/foo &&
 448        git update-ref $prefix/foo $C &&
 449        cat >expected <<-EOF &&
 450        fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
 451        EOF
 452        printf "%s\n" "option no-deref" "create $prefix/symref $E" |
 453        test_must_fail git update-ref --stdin 2>output.err &&
 454        test_cmp expected output.err
 455'
 456
 457test_expect_success 'incorrect old value blocks indirect no-deref delete' '
 458        prefix=refs/incorrect-noderef-delete &&
 459        git symbolic-ref $prefix/symref $prefix/foo &&
 460        git update-ref $prefix/foo $C &&
 461        cat >expected <<-EOF &&
 462        fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
 463        EOF
 464        printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
 465        test_must_fail git update-ref --stdin 2>output.err &&
 466        test_cmp expected output.err
 467'
 468
 469test_expect_success 'non-empty directory blocks create' '
 470        prefix=refs/ne-create &&
 471        mkdir -p .git/$prefix/foo/bar &&
 472        : >.git/$prefix/foo/bar/baz.lock &&
 473        test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
 474        cat >expected <<-EOF &&
 475        fatal: cannot lock ref $SQ$prefix/foo$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
 476        EOF
 477        printf "%s\n" "update $prefix/foo $C" |
 478        test_must_fail git update-ref --stdin 2>output.err &&
 479        test_cmp expected output.err &&
 480        cat >expected <<-EOF &&
 481        fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
 482        EOF
 483        printf "%s\n" "update $prefix/foo $D $C" |
 484        test_must_fail git update-ref --stdin 2>output.err &&
 485        test_cmp expected output.err
 486'
 487
 488test_expect_success 'broken reference blocks create' '
 489        prefix=refs/broken-create &&
 490        mkdir -p .git/$prefix &&
 491        echo "gobbledigook" >.git/$prefix/foo &&
 492        test_when_finished "rm -f .git/$prefix/foo" &&
 493        cat >expected <<-EOF &&
 494        fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
 495        EOF
 496        printf "%s\n" "update $prefix/foo $C" |
 497        test_must_fail git update-ref --stdin 2>output.err &&
 498        test_cmp expected output.err &&
 499        cat >expected <<-EOF &&
 500        fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
 501        EOF
 502        printf "%s\n" "update $prefix/foo $D $C" |
 503        test_must_fail git update-ref --stdin 2>output.err &&
 504        test_cmp expected output.err
 505'
 506
 507test_expect_success 'non-empty directory blocks indirect create' '
 508        prefix=refs/ne-indirect-create &&
 509        git symbolic-ref $prefix/symref $prefix/foo &&
 510        mkdir -p .git/$prefix/foo/bar &&
 511        : >.git/$prefix/foo/bar/baz.lock &&
 512        test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
 513        cat >expected <<-EOF &&
 514        fatal: cannot lock ref $SQ$prefix/symref$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
 515        EOF
 516        printf "%s\n" "update $prefix/symref $C" |
 517        test_must_fail git update-ref --stdin 2>output.err &&
 518        test_cmp expected output.err &&
 519        cat >expected <<-EOF &&
 520        fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
 521        EOF
 522        printf "%s\n" "update $prefix/symref $D $C" |
 523        test_must_fail git update-ref --stdin 2>output.err &&
 524        test_cmp expected output.err
 525'
 526
 527test_expect_success 'broken reference blocks indirect create' '
 528        prefix=refs/broken-indirect-create &&
 529        git symbolic-ref $prefix/symref $prefix/foo &&
 530        echo "gobbledigook" >.git/$prefix/foo &&
 531        test_when_finished "rm -f .git/$prefix/foo" &&
 532        cat >expected <<-EOF &&
 533        fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
 534        EOF
 535        printf "%s\n" "update $prefix/symref $C" |
 536        test_must_fail git update-ref --stdin 2>output.err &&
 537        test_cmp expected output.err &&
 538        cat >expected <<-EOF &&
 539        fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
 540        EOF
 541        printf "%s\n" "update $prefix/symref $D $C" |
 542        test_must_fail git update-ref --stdin 2>output.err &&
 543        test_cmp expected output.err
 544'
 545
 546test_expect_success 'no bogus intermediate values during delete' '
 547        prefix=refs/slow-transaction &&
 548        # Set up a reference with differing loose and packed versions:
 549        git update-ref $prefix/foo $C &&
 550        git pack-refs --all &&
 551        git update-ref $prefix/foo $D &&
 552        git for-each-ref $prefix >unchanged &&
 553        # Now try to update the reference, but hold the `packed-refs` lock
 554        # for a while to see what happens while the process is blocked:
 555        : >.git/packed-refs.lock &&
 556        test_when_finished "rm -f .git/packed-refs.lock" &&
 557        {
 558                # Note: the following command is intentionally run in the
 559                # background. We increase the timeout so that `update-ref`
 560                # attempts to acquire the `packed-refs` lock for much longer
 561                # than it takes for us to do the check then delete it:
 562                git -c core.packedrefstimeout=30000 update-ref -d $prefix/foo &
 563        } &&
 564        pid2=$! &&
 565        # Give update-ref plenty of time to get to the point where it tries
 566        # to lock packed-refs:
 567        sleep 1 &&
 568        # Make sure that update-ref did not complete despite the lock:
 569        kill -0 $pid2 &&
 570        # Verify that the reference still has its old value:
 571        sha1=$(git rev-parse --verify --quiet $prefix/foo || echo undefined) &&
 572        case "$sha1" in
 573        $D)
 574                # This is what we hope for; it means that nothing
 575                # user-visible has changed yet.
 576                : ;;
 577        undefined)
 578                # This is not correct; it means the deletion has happened
 579                # already even though update-ref should not have been
 580                # able to acquire the lock yet.
 581                echo "$prefix/foo deleted prematurely" &&
 582                break
 583                ;;
 584        $C)
 585                # This value should never be seen. Probably the loose
 586                # reference has been deleted but the packed reference
 587                # is still there:
 588                echo "$prefix/foo incorrectly observed to be C" &&
 589                break
 590                ;;
 591        *)
 592                # WTF?
 593                echo "unexpected value observed for $prefix/foo: $sha1" &&
 594                break
 595                ;;
 596        esac >out &&
 597        rm -f .git/packed-refs.lock &&
 598        wait $pid2 &&
 599        test_must_be_empty out &&
 600        test_must_fail git rev-parse --verify --quiet $prefix/foo
 601'
 602
 603test_expect_success 'delete fails cleanly if packed-refs file is locked' '
 604        prefix=refs/locked-packed-refs &&
 605        # Set up a reference with differing loose and packed versions:
 606        git update-ref $prefix/foo $C &&
 607        git pack-refs --all &&
 608        git update-ref $prefix/foo $D &&
 609        git for-each-ref $prefix >unchanged &&
 610        # Now try to delete it while the `packed-refs` lock is held:
 611        : >.git/packed-refs.lock &&
 612        test_when_finished "rm -f .git/packed-refs.lock" &&
 613        test_must_fail git update-ref -d $prefix/foo >out 2>err &&
 614        git for-each-ref $prefix >actual &&
 615        test_i18ngrep "Unable to create $SQ.*packed-refs.lock$SQ: " err &&
 616        test_cmp unchanged actual
 617'
 618
 619test_expect_success 'delete fails cleanly if packed-refs.new write fails' '
 620        # Setup and expectations are similar to the test above.
 621        prefix=refs/failed-packed-refs &&
 622        git update-ref $prefix/foo $C &&
 623        git pack-refs --all &&
 624        git update-ref $prefix/foo $D &&
 625        git for-each-ref $prefix >unchanged &&
 626        # This should not happen in practice, but it is an easy way to get a
 627        # reliable error (we open with create_tempfile(), which uses O_EXCL).
 628        : >.git/packed-refs.new &&
 629        test_when_finished "rm -f .git/packed-refs.new" &&
 630        test_must_fail git update-ref -d $prefix/foo &&
 631        git for-each-ref $prefix >actual &&
 632        test_cmp unchanged actual
 633'
 634
 635test_done