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