refs: resolve symbolic refs first

Before committing ref updates, split symbolic ref updates into two parts: an update to the underlying ref, and a log-only update to the symbolic ref. This ensures that both references are locked correctly during the transaction, including while their reflogs are updated. Similarly, if the reference pointed to by HEAD is modified directly, add a separate log-only update to HEAD, rather than leaving the job of updating HEAD's reflog to commit_ref_update(). This change ensures that HEAD is locked correctly while its reflog is being modified, as well as being cheaper (HEAD only needs to be resolved once). This makes use of a new function, lock_raw_ref(), which is analogous to read_raw_ref(), but acquires a lock on the reference before reading it. This change still has two problems: * There are redundant read_ref_full() reference lookups. * It is still possible to get incorrect reflogs for symbolic references if there is a concurrent update by another process, since the old_oid of a symref is determined before the lock on the pointed-to ref is held. Both problems will soon be fixed. Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> WIP

Michael Haggerty committed Apr 25, 2016 at 15:56 UTC 92b1551b1d407065f961ffd1d972481063a0edcc
3 files changed +514 -40
refs/files-backend.c
+470 -38
@@ -1526,6 +1526,233 @@ static void unlock_ref(struct ref_lock *lock)
1526 free(lock);
1527 }
1528
1529 +/*
1530 + * Lock refname, without following symrefs, and set *lock_p to point
1531 + * at a newly-allocated lock object. Fill in lock->old_oid, referent,
1532 + * and type similarly to read_raw_ref().
1533 + *
1534 + * The caller must verify that refname is a "safe" reference name (in
1535 + * the sense of refname_is_safe()) before calling this function.
1536 + *
1537 + * If the reference doesn't already exist, verify that refname doesn't
1538 + * have a D/F conflict with any existing references. extras and skip
1539 + * are passed to verify_refname_available_dir() for this check.
1540 + *
1541 + * If mustexist is not set and the reference is not found or is
1542 + * broken, lock the reference anyway but clear sha1.
1543 + *
1544 + * Return 0 on success. On failure, write an error message to err and
1545 + * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR.
1546 + *
1547 + * Implementation note: This function is basically
1548 + *
1549 + * lock reference
1550 + * read_raw_ref()
1551 + *
1552 + * but it includes a lot more code to
1553 + * - Deal with possible races with other processes
1554 + * - Avoid calling verify_refname_available_dir() when it can be
1555 + * avoided, namely if we were successfully able to read the ref
1556 + * - Generate informative error messages in the case of failure
1557 + */
1558 +static int lock_raw_ref(const char *refname, int mustexist,
1559 + const struct string_list *extras,
1560 + const struct string_list *skip,
1561 + struct ref_lock **lock_p,
1562 + struct strbuf *referent,
1563 + unsigned int *type,
1564 + struct strbuf *err)
1565 +{
1566 + struct ref_lock *lock;
1567 + struct strbuf ref_file = STRBUF_INIT;
1568 + int attempts_remaining = 3;
1569 + int ret = TRANSACTION_GENERIC_ERROR;
1570 +
1571 + assert(err);
1572 + *type = 0;
1573 +
1574 + /* First lock the file so it can't change out from under us. */
1575 +
1576 + *lock_p = lock = xcalloc(1, sizeof(*lock));
1577 +
1578 + lock->ref_name = xstrdup(refname);
1579 + lock->orig_ref_name = xstrdup(refname);
1580 + strbuf_git_path(&ref_file, "%s", refname);
1581 +
1582 +retry:
1583 + switch (safe_create_leading_directories(ref_file.buf)) {
1584 + case SCLD_OK:
1585 + break; /* success */
1586 + case SCLD_EXISTS:
1587 + /*
1588 + * Suppose refname is "refs/foo/bar". We just failed
1589 + * to create the containing directory, "refs/foo",
1590 + * because there was a non-directory in the way. This
1591 + * indicates a D/F conflict, probably because of
1592 + * another reference such as "refs/foo". There is no
1593 + * reason to expect this error to be transitory.
1594 + */
1595 + if (verify_refname_available(refname, extras, skip, err)) {
1596 + if (mustexist) {
1597 + /*
1598 + * To the user the relevant error is
1599 + * that the "mustexist" reference is
1600 + * missing:
1601 + */
1602 + strbuf_reset(err);
1603 + strbuf_addf(err, "unable to resolve reference '%s'",
1604 + refname);
1605 + } else {
1606 + /*
1607 + * The error message set by
1608 + * verify_refname_available_dir() is OK.
1609 + */
1610 + ret = TRANSACTION_NAME_CONFLICT;
1611 + }
1612 + } else {
1613 + /*
1614 + * The file that is in the way isn't a loose
1615 + * reference. Report it as a low-level
1616 + * failure.
1617 + */
1618 + strbuf_addf(err, "unable to create lock file %s.lock; "
1619 + "non-directory in the way",
1620 + ref_file.buf);
1621 + }
1622 + goto error_return;
1623 + case SCLD_VANISHED:
1624 + /* Maybe another process was tidying up. Try again. */
1625 + if (--attempts_remaining > 0)
1626 + goto retry;
1627 + /* fall through */
1628 + default:
1629 + strbuf_addf(err, "unable to create directory for %s",
1630 + ref_file.buf);
1631 + goto error_return;
1632 + }
1633 +
1634 + if (!lock->lk)
1635 + lock->lk = xcalloc(1, sizeof(struct lock_file));
1636 +
1637 + if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
1638 + if (errno == ENOENT && --attempts_remaining > 0) {
1639 + /*
1640 + * Maybe somebody just deleted one of the
1641 + * directories leading to ref_file. Try
1642 + * again:
1643 + */
1644 + goto retry;
1645 + } else {
1646 + unable_to_lock_message(ref_file.buf, errno, err);
1647 + goto error_return;
1648 + }
1649 + }
1650 +
1651 + /*
1652 + * Now we hold the lock and can read the reference without
1653 + * fear that its value will change.
1654 + */
1655 +
1656 + if (read_raw_ref(refname, lock->old_oid.hash, referent, type)) {
1657 + if (errno == ENOENT) {
1658 + if (mustexist) {
1659 + /* Garden variety missing reference. */
1660 + strbuf_addf(err, "unable to resolve reference '%s'",
1661 + refname);
1662 + goto error_return;
1663 + } else {
1664 + /*
1665 + * Reference is missing, but that's OK. We
1666 + * know that there is not a conflict with
1667 + * another loose reference because
1668 + * (supposing that we are trying to lock
1669 + * reference "refs/foo/bar"):
1670 + *
1671 + * - We were successfully able to create
1672 + * the lockfile refs/foo/bar.lock, so we
1673 + * know there cannot be a loose reference
1674 + * named "refs/foo".
1675 + *
1676 + * - We got ENOENT and not EISDIR, so we
1677 + * know that there cannot be a loose
1678 + * reference named "refs/foo/bar/baz".
1679 + */
1680 + }
1681 + } else if (errno == EISDIR) {
1682 + /*
1683 + * There is a directory in the way. It might have
1684 + * contained references that have been deleted. If
1685 + * we don't require that the reference already
1686 + * exists, try to remove the directory so that it
1687 + * doesn't cause trouble when we want to rename the
1688 + * lockfile into place later.
1689 + */
1690 + if (mustexist) {
1691 + /* Garden variety missing reference. */
1692 + strbuf_addf(err, "unable to resolve reference '%s'",
1693 + refname);
1694 + goto error_return;
1695 + } else if (remove_dir_recursively(&ref_file,
1696 + REMOVE_DIR_EMPTY_ONLY)) {
1697 + if (verify_refname_available_dir(
1698 + refname, extras, skip,
1699 + get_loose_refs(&ref_cache),
1700 + err)) {
1701 + /*
1702 + * The error message set by
1703 + * verify_refname_available() is OK.
1704 + */
1705 + ret = TRANSACTION_NAME_CONFLICT;
1706 + goto error_return;
1707 + } else {
1708 + /*
1709 + * We can't delete the directory,
1710 + * but we also don't know of any
1711 + * references that it should
1712 + * contain.
1713 + */
1714 + strbuf_addf(err, "there is a non-empty directory '%s' "
1715 + "blocking reference '%s'",
1716 + ref_file.buf, refname);
1717 + goto error_return;
1718 + }
1719 + }
1720 + } else if (errno == EINVAL && (*type & REF_ISBROKEN)) {
1721 + strbuf_addf(err, "unable to resolve reference '%s': "
1722 + "reference broken", refname);
1723 + goto error_return;
1724 + } else {
1725 + strbuf_addf(err, "unable to resolve reference '%s': %s",
1726 + refname, strerror(errno));
1727 + goto error_return;
1728 + }
1729 +
1730 + /*
1731 + * If the ref did not exist and we are creating it,
1732 + * make sure there is no existing packed ref whose
1733 + * name begins with our refname, nor a packed ref
1734 + * whose name is a proper prefix of our refname.
1735 + */
1736 + if (verify_refname_available_dir(
1737 + refname, extras, skip,
1738 + get_packed_refs(&ref_cache),
1739 + err)) {
1740 + goto error_return;
1741 + }
1742 + }
1743 +
1744 + ret = 0;
1745 + goto out;
1746 +
1747 +error_return:
1748 + unlock_ref(lock);
1749 + *lock_p = NULL;
1750 +
1751 +out:
1752 + strbuf_release(&ref_file);
1753 + return ret;
1754 +}
1755 +
1756 /*
1757 * Peel the entry (if possible) and return its new peel_status. If
1758 * repeel is true, re-peel the entry even if there is an old peeled
@@ -3052,55 +3279,202 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
3279 }
3280
3281 /*
3055 - * Acquire all locks, verify old values if provided, check
3056 - * that new values are valid, and write new values to the
3057 - * lockfiles, ready to be activated. Only keep one lockfile
3058 - * open at a time to avoid running out of file descriptors.
3282 + * If update is a direct update of head_ref (the reference pointed to
3283 + * by HEAD), then add an extra REF_LOG_ONLY update for HEAD.
3284 + */
3285 +static int split_head_update(struct ref_update *update,
3286 + struct ref_transaction *transaction,
3287 + const char *head_ref,
3288 + struct string_list *affected_refnames,
3289 + struct strbuf *err)
3290 +{
3291 + struct string_list_item *item;
3292 + struct ref_update *new_update;
3293 +
3294 + if ((update->flags & REF_LOG_ONLY) ||
3295 + (update->flags & REF_ISPRUNING) ||
3296 + (update->flags & REF_UPDATE_VIA_HEAD))
3297 + return 0;
3298 +
3299 + if (strcmp(update->refname, head_ref))
3300 + return 0;
3301 +
3302 + /*
3303 + * First make sure that HEAD is not already in the
3304 + * transaction. This insertion is O(N) in the transaction
3305 + * size, but it happens at most once per transaction.
3306 + */
3307 + item = string_list_insert(affected_refnames, "HEAD");
3308 + if (item->util) {
3309 + /* An entry already existed */
3310 + strbuf_addf(err,
3311 + "multiple updates for 'HEAD' (including one "
3312 + "via its referent '%s') are not allowed",
3313 + update->refname);
3314 + return TRANSACTION_NAME_CONFLICT;
3315 + }
3316 +
3317 + new_update = ref_transaction_add_update(
3318 + transaction, "HEAD",
3319 + update->flags | REF_LOG_ONLY | REF_NODEREF,
3320 + update->new_sha1, update->old_sha1,
3321 + update->msg);
3322 +
3323 + item->util = new_update;
3324 +
3325 + return 0;
3326 +}
3327 +
3328 +/*
3329 + * update is for a symref that points at referent and doesn't have
3330 + * REF_NODEREF set. Split it into two updates:
3331 + * - The original update, but with REF_LOG_ONLY and REF_NODEREF set
3332 + * - A new, separate update for the referent reference
3333 + * Note that the new update will itself be subject to splitting when
3334 + * the iteration gets to it.
3335 + */
3336 +static int split_symref_update(struct ref_update *update,
3337 + const char *referent,
3338 + struct ref_transaction *transaction,
3339 + struct string_list *affected_refnames,
3340 + struct strbuf *err)
3341 +{
3342 + struct string_list_item *item;
3343 + struct ref_update *new_update;
3344 + unsigned int new_flags;
3345 +
3346 + /*
3347 + * First make sure that referent is not already in the
3348 + * transaction. This insertion is O(N) in the transaction
3349 + * size, but it happens at most once per symref in a
3350 + * transaction.
3351 + */
3352 + item = string_list_insert(affected_refnames, referent);
3353 + if (item->util) {
3354 + /* An entry already existed */
3355 + strbuf_addf(err,
3356 + "multiple updates for '%s' (including one "
3357 + "via symref '%s') are not allowed",
3358 + referent, update->refname);
3359 + return TRANSACTION_NAME_CONFLICT;
3360 + }
3361 +
3362 + new_flags = update->flags;
3363 + if (!strcmp(update->refname, "HEAD")) {
3364 + /*
3365 + * Record that the new update came via HEAD, so that
3366 + * when we process it, split_head_update() doesn't try
3367 + * to add another reflog update for HEAD. Note that
3368 + * this bit will be propagated if the new_update
3369 + * itself needs to be split.
3370 + */
3371 + new_flags |= REF_UPDATE_VIA_HEAD;
3372 + }
3373 +
3374 + new_update = ref_transaction_add_update(
3375 + transaction, referent, new_flags,
3376 + update->new_sha1, update->old_sha1,
3377 + update->msg);
3378 +
3379 + /* Change the symbolic ref update to log only: */
3380 + update->flags |= REF_LOG_ONLY | REF_NODEREF;
3381 +
3382 + item->util = new_update;
3383 +
3384 + return 0;
3385 +}
3386 +
3387 +/*
3388 + * Prepare for carrying out update:
3389 + * - Lock the reference referred to by update.
3390 + * - Read the reference under lock.
3391 + * - Check that its old SHA-1 value (if specified) is correct, and in
3392 + * any case record it in update->lock->old_oid for later use when
3393 + * writing the reflog.
3394 + * - If it is a symref update without REF_NODEREF, split it up into a
3395 + * REF_LOG_ONLY update of the symref and add a separate update for
3396 + * the referent to transaction.
3397 + * - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
3398 + * update of HEAD.
3399 */
3400 static int lock_ref_for_update(struct ref_update *update,
3401 struct ref_transaction *transaction,
3402 + const char *head_ref,
3403 struct string_list *affected_refnames,
3404 struct strbuf *err)
3405 {
3406 + struct strbuf referent = STRBUF_INIT;
3407 + int mustexist = (update->flags & REF_HAVE_OLD) &&
3408 + !is_null_sha1(update->old_sha1);
3409 int ret;
3410 + struct ref_lock *lock;
3411
3067 - if ((update->flags & REF_HAVE_NEW) &&
3068 - is_null_sha1(update->new_sha1))
3412 + if ((update->flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1))
3413 update->flags |= REF_DELETING;
3070 - update->lock = lock_ref_sha1_basic(
3071 - update->refname,
3072 - ((update->flags & REF_HAVE_OLD) ?
3073 - update->old_sha1 : NULL),
3074 - affected_refnames, NULL,
3075 - update->flags,
3076 - &update->type,
3077 - err);
3078 - if (!update->lock) {
3414 +
3415 + if (head_ref) {
3416 + ret = split_head_update(update, transaction, head_ref,
3417 + affected_refnames, err);
3418 + if (ret)
3419 + return ret;
3420 + }
3421 +
3422 + ret = lock_raw_ref(update->refname, mustexist,
3423 + affected_refnames, NULL,
3424 + &update->lock, &referent,
3425 + &update->type, err);
3426 +
3427 + if (ret) {
3428 char *reason;
3429
3081 - ret = (errno == ENOTDIR)
3082 - ? TRANSACTION_NAME_CONFLICT
3083 - : TRANSACTION_GENERIC_ERROR;
3430 reason = strbuf_detach(err, NULL);
3431 strbuf_addf(err, "cannot lock ref '%s': %s",
3432 update->refname, reason);
3433 free(reason);
3434 return ret;
3435 }
3436 +
3437 + lock = update->lock;
3438 +
3439 + if (read_ref_full(update->refname,
3440 + mustexist ? RESOLVE_REF_READING : 0,
3441 + lock->old_oid.hash, NULL)) {
3442 + if (update->flags & REF_HAVE_OLD) {
3443 + strbuf_addf(err, "cannot lock ref '%s': can't resolve old value",
3444 + update->refname);
3445 + return TRANSACTION_GENERIC_ERROR;
3446 + } else {
3447 + hashclr(lock->old_oid.hash);
3448 + }
3449 + }
3450 + if ((update->flags & REF_HAVE_OLD) &&
3451 + hashcmp(lock->old_oid.hash, update->old_sha1)) {
3452 + strbuf_addf(err, "cannot lock ref '%s': is at %s but expected %s",
3453 + update->refname,
3454 + sha1_to_hex(lock->old_oid.hash),
3455 + sha1_to_hex(update->old_sha1));
3456 + return TRANSACTION_GENERIC_ERROR;
3457 + }
3458 +
3459 + if (update->type & REF_ISSYMREF) {
3460 + if (!(update->flags & REF_NODEREF)) {
3461 + ret = split_symref_update(update, referent.buf, transaction,
3462 + affected_refnames, err);
3463 + if (ret)
3464 + return ret;
3465 + }
3466 + }
3467 +
3468 if ((update->flags & REF_HAVE_NEW) &&
3469 !(update->flags & REF_DELETING) &&
3470 !(update->flags & REF_LOG_ONLY)) {
3093 - int overwriting_symref = ((update->type & REF_ISSYMREF) &&
3094 - (update->flags & REF_NODEREF));
3095 -
3096 - if (!overwriting_symref &&
3097 - !hashcmp(update->lock->old_oid.hash, update->new_sha1)) {
3471 + if (!(update->type & REF_ISSYMREF) &&
3472 + !hashcmp(lock->old_oid.hash, update->new_sha1)) {
3473 /*
3474 * The reference already has the desired
3475 * value, so we don't need to write it.
3476 */
3102 - } else if (write_ref_to_lockfile(update->lock,
3103 - update->new_sha1,
3477 + } else if (write_ref_to_lockfile(lock, update->new_sha1,
3478 err)) {
3479 char *write_err = strbuf_detach(err, NULL);
3480
@@ -3124,7 +3498,7 @@ static int lock_ref_for_update(struct ref_update *update,
3498 * the lockfile is still open. Close it to
3499 * free up the file descriptor:
3500 */
3127 - if (close_ref(update->lock)) {
3501 + if (close_ref(lock)) {
3502 strbuf_addf(err, "couldn't close '%s.lock'",
3503 update->refname);
3504 return TRANSACTION_GENERIC_ERROR;
@@ -3140,6 +3514,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3514 struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
3515 struct string_list_item *ref_to_delete;
3516 struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
3517 + char *head_ref = NULL;
3518 + int head_type;
3519 + struct object_id head_oid;
3520
3521 assert(err);
3522
@@ -3151,16 +3528,57 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3528 return 0;
3529 }
3530
3154 - /* Fail if a refname appears more than once in the transaction: */
3155 - for (i = 0; i < transaction->nr; i++)
3156 - string_list_append(&affected_refnames,
3157 - transaction->updates[i]->refname);
3531 + /*
3532 + * Fail if a refname appears more than once in the
3533 + * transaction. (If we end up splitting up any updates using
3534 + * split_symref_update() or split_head_update(), those
3535 + * functions will check that the new updates don't have the
3536 + * same refname as any existing ones.)
3537 + */
3538 + for (i = 0; i < transaction->nr; i++) {
3539 + struct ref_update *update = transaction->updates[i];
3540 + struct string_list_item *item =
3541 + string_list_append(&affected_refnames, update->refname);
3542 +
3543 + /*
3544 + * We store a pointer to update in item->util, but at
3545 + * the moment we never use the value of this field
3546 + * except to check whether it is non-NULL.
3547 + */
3548 + item->util = update;
3549 + }
3550 string_list_sort(&affected_refnames);
3551 if (ref_update_reject_duplicates(&affected_refnames, err)) {
3552 ret = TRANSACTION_GENERIC_ERROR;
3553 goto cleanup;
3554 }
3555
3556 + /*
3557 + * Special hack: If a branch is updated directly and HEAD
3558 + * points to it (may happen on the remote side of a push
3559 + * for example) then logically the HEAD reflog should be
3560 + * updated too.
3561 + *
3562 + * A generic solution would require reverse symref lookups,
3563 + * but finding all symrefs pointing to a given branch would be
3564 + * rather costly for this rare event (the direct update of a
3565 + * branch) to be worth it. So let's cheat and check with HEAD
3566 + * only, which should cover 99% of all usage scenarios (even
3567 + * 100% of the default ones).
3568 + *
3569 + * So if HEAD is a symbolic reference, then record the name of
3570 + * the reference that it points to. If we see an update of
3571 + * head_ref within the transaction, then split_head_update()
3572 + * arranges for the reflog of HEAD to be updated, too.
3573 + */
3574 + head_ref = resolve_refdup("HEAD", RESOLVE_REF_NO_RECURSE,
3575 + head_oid.hash, &head_type);
3576 +
3577 + if (head_ref && !(head_type & REF_ISSYMREF)) {
3578 + free(head_ref);
3579 + head_ref = NULL;
3580 + }
3581 +
3582 /*
3583 * Acquire all locks, verify old values if provided, check
3584 * that new values are valid, and write new values to the
@@ -3170,7 +3588,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3588 for (i = 0; i < transaction->nr; i++) {
3589 struct ref_update *update = transaction->updates[i];
3590
3173 - ret = lock_ref_for_update(update, transaction,
3591 + ret = lock_ref_for_update(update, transaction, head_ref,
3592 &affected_refnames, err);
3593 if (ret)
3594 goto cleanup;
@@ -3179,23 +3597,35 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3597 /* Perform updates first so live commits remain referenced */
3598 for (i = 0; i < transaction->nr; i++) {
3599 struct ref_update *update = transaction->updates[i];
3600 + struct ref_lock *lock = update->lock;
3601
3602 if (update->flags & REF_NEEDS_COMMIT ||
3603 update->flags & REF_LOG_ONLY) {
3185 - if (commit_ref_update(update->lock,
3186 - update->new_sha1, update->msg,
3187 - update->flags, err)) {
3188 - /* freed by commit_ref_update(): */
3604 + if (log_ref_write(lock->ref_name, lock->old_oid.hash,
3605 + update->new_sha1,
3606 + update->msg, update->flags, err)) {
3607 + char *old_msg = strbuf_detach(err, NULL);
3608 +
3609 + strbuf_addf(err, "cannot update the ref '%s': %s",
3610 + lock->ref_name, old_msg);
3611 + free(old_msg);
3612 + unlock_ref(lock);
3613 update->lock = NULL;
3614 ret = TRANSACTION_GENERIC_ERROR;
3615 goto cleanup;
3192 - } else {
3193 - /* freed by commit_ref_update(): */
3616 + }
3617 + }
3618 + if (update->flags & REF_NEEDS_COMMIT) {
3619 + clear_loose_ref_cache(&ref_cache);
3620 + if (commit_ref(lock)) {
3621 + strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
3622 + unlock_ref(lock);
3623 update->lock = NULL;
3624 + ret = TRANSACTION_GENERIC_ERROR;
3625 + goto cleanup;
3626 }
3627 }
3628 }
3198 -
3629 /* Perform deletes now that updates are safely completed */
3630 for (i = 0; i < transaction->nr; i++) {
3631 struct ref_update *update = transaction->updates[i];
@@ -3228,7 +3658,9 @@ cleanup:
3658 if (transaction->updates[i]->lock)
3659 unlock_ref(transaction->updates[i]->lock);
3660 string_list_clear(&refs_to_delete, 0);
3661 + free(head_ref);
3662 string_list_clear(&affected_refnames, 0);
3663 +
3664 return ret;
3665 }
3666
refs/refs-internal.h
+9 -2
@@ -49,6 +49,12 @@
49 */
50 #define REF_LOG_ONLY 0x80
51
52 +/*
53 + * Internal flag, meaning that the containing ref_update was via an
54 + * update to HEAD.
55 + */
56 +#define REF_UPDATE_VIA_HEAD 0x100
57 +
58 /*
59 * Return true iff refname is minimally safe. "Safe" here means that
60 * deleting a loose reference by this name will not do any damage, for
@@ -148,11 +154,12 @@ struct ref_update {
154 unsigned char old_sha1[20];
155 /*
156 * One or more of REF_HAVE_NEW, REF_HAVE_OLD, REF_NODEREF,
151 - * REF_DELETING, and REF_ISPRUNING:
157 + * REF_DELETING, REF_ISPRUNING, REF_LOG_ONLY, and
158 + * REF_UPDATE_VIA_HEAD:
159 */
160 unsigned int flags;
161 struct ref_lock *lock;
155 - int type;
162 + unsigned int type;
163 char *msg;
164 const char refname[FLEX_ARRAY];
165 };
t/t1400-update-ref.sh
+35
@@ -1102,6 +1102,41 @@ test_expect_success 'stdin -z delete refs works with packed and loose refs' '
1102 test_must_fail git rev-parse --verify -q $c
1103 '
1104
1105 +test_expect_success 'fails with duplicate HEAD update' '
1106 + git branch target1 $A &&
1107 + git checkout target1 &&
1108 + cat >stdin <<-EOF &&
1109 + update refs/heads/target1 $C
1110 + option no-deref
1111 + update HEAD $B
1112 + EOF
1113 + test_must_fail git update-ref --stdin <stdin 2>err &&
1114 + grep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err &&
1115 + echo "refs/heads/target1" >expect &&
1116 + git symbolic-ref HEAD >actual &&
1117 + test_cmp expect actual &&
1118 + echo "$A" >expect &&
1119 + git rev-parse refs/heads/target1 >actual &&
1120 + test_cmp expect actual
1121 +'
1122 +
1123 +test_expect_success 'fails with duplicate ref update via symref' '
1124 + git branch target2 $A &&
1125 + git symbolic-ref refs/heads/symref2 refs/heads/target2 &&
1126 + cat >stdin <<-EOF &&
1127 + update refs/heads/target2 $C
1128 + update refs/heads/symref2 $B
1129 + EOF
1130 + test_must_fail git update-ref --stdin <stdin 2>err &&
1131 + grep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err &&
1132 + echo "refs/heads/target2" >expect &&
1133 + git symbolic-ref refs/heads/symref2 >actual &&
1134 + test_cmp expect actual &&
1135 + echo "$A" >expect &&
1136 + git rev-parse refs/heads/target2 >actual &&
1137 + test_cmp expect actual
1138 +'
1139 +
1140 run_with_limited_open_files () {
1141 (ulimit -n 32 && "$@")
1142 }