refs.c: ref_transaction_commit: distinguish name conflicts from other errors

In _commit, ENOTDIR can happen in the call to lock_ref_sha1_basic, either when we lstat the new refname or if the name checking function reports that the same type of conflict happened. In both cases, it means that we can not create the new ref due to a name conflict. Start defining specific return codes for _commit. TRANSACTION_NAME_CONFLICT refers to a failure to create a ref due to a name conflict with another ref. TRANSACTION_GENERIC_ERROR is for all other errors. When "git fetch" is creating refs, name conflicts differ from other errors in that they are likely to be resolved by running "git remote prune <remote>". "git fetch" currently inspects errno to decide whether to give that advice. Once it switches to the transaction API, it can check for TRANSACTION_NAME_CONFLICT instead. Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ronnie Sahlberg committed May 16, 2014 at 14:14 UTC 28e6a97e39edb84599693db971e36d793d36e413
2 files changed +23 -12
refs.c
+16 -10
@@ -3637,9 +3637,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3637
3638 /* Copy, sort, and reject duplicate refs */
3639 qsort(updates, n, sizeof(*updates), ref_update_compare);
3640 - ret = ref_update_reject_duplicates(updates, n, err);
3641 - if (ret)
3640 + if (ref_update_reject_duplicates(updates, n, err)) {
3641 + ret = TRANSACTION_GENERIC_ERROR;
3642 goto cleanup;
3643 + }
3644
3645 /* Acquire all locks while verifying old values */
3646 for (i = 0; i < n; i++) {
@@ -3653,10 +3654,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3654 update->flags,
3655 &update->type);
3656 if (!update->lock) {
3657 + ret = (errno == ENOTDIR)
3658 + ? TRANSACTION_NAME_CONFLICT
3659 + : TRANSACTION_GENERIC_ERROR;
3660 if (err)
3661 strbuf_addf(err, "Cannot lock the ref '%s'.",
3662 update->refname);
3659 - ret = 1;
3663 goto cleanup;
3664 }
3665 }
@@ -3666,15 +3669,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3669 struct ref_update *update = updates[i];
3670
3671 if (!is_null_sha1(update->new_sha1)) {
3669 - ret = write_ref_sha1(update->lock, update->new_sha1,
3670 - update->msg);
3671 - update->lock = NULL; /* freed by write_ref_sha1 */
3672 - if (ret) {
3672 + if (write_ref_sha1(update->lock, update->new_sha1,
3673 + update->msg)) {
3674 + update->lock = NULL; /* freed by write_ref_sha1 */
3675 if (err)
3676 strbuf_addf(err, "Cannot update the ref '%s'.",
3677 update->refname);
3678 + ret = TRANSACTION_GENERIC_ERROR;
3679 goto cleanup;
3680 }
3681 + update->lock = NULL; /* freed by write_ref_sha1 */
3682 }
3683 }
3684
@@ -3683,14 +3687,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3687 struct ref_update *update = updates[i];
3688
3689 if (update->lock) {
3686 - ret |= delete_ref_loose(update->lock, update->type,
3687 - err);
3690 + if (delete_ref_loose(update->lock, update->type, err))
3691 + ret = TRANSACTION_GENERIC_ERROR;
3692 +
3693 if (!(update->flags & REF_ISPRUNING))
3694 delnames[delnum++] = update->lock->ref_name;
3695 }
3696 }
3697
3693 - ret |= repack_without_refs(delnames, delnum, err);
3698 + if (repack_without_refs(delnames, delnum, err))
3699 + ret = TRANSACTION_GENERIC_ERROR;
3700 for (i = 0; i < delnum; i++)
3701 unlink_or_warn(git_path("logs/%s", delnames[i]));
3702 clear_loose_ref_cache(&ref_cache);
refs.h
+7 -2
@@ -326,9 +326,14 @@ int ref_transaction_delete(struct ref_transaction *transaction,
326
327 /*
328 * Commit all of the changes that have been queued in transaction, as
329 - * atomically as possible. Return a nonzero value if there is a
330 - * problem.
329 + * atomically as possible.
330 + *
331 + * Returns 0 for success, or one of the below error codes for errors.
332 */
333 +/* Naming conflict (for example, the ref names A and A/B conflict). */
334 +#define TRANSACTION_NAME_CONFLICT -1
335 +/* All other errors. */
336 +#define TRANSACTION_GENERIC_ERROR -2
337 int ref_transaction_commit(struct ref_transaction *transaction,
338 struct strbuf *err);
339