diff --git a/refs.c b/refs.c index a007cf325..9d9bbebfb 100644 --- a/refs.c +++ b/refs.c @@ -3637,9 +3637,10 @@ int ref_transaction_commit(struct ref_transaction *transaction, /* Copy, sort, and reject duplicate refs */ qsort(updates, n, sizeof(*updates), ref_update_compare); - ret = ref_update_reject_duplicates(updates, n, err); - if (ret) + if (ref_update_reject_duplicates(updates, n, err)) { + ret = TRANSACTION_GENERIC_ERROR; goto cleanup; + } /* Acquire all locks while verifying old values */ for (i = 0; i < n; i++) { @@ -3653,10 +3654,12 @@ int ref_transaction_commit(struct ref_transaction *transaction, update->flags, &update->type); if (!update->lock) { + ret = (errno == ENOTDIR) + ? TRANSACTION_NAME_CONFLICT + : TRANSACTION_GENERIC_ERROR; if (err) strbuf_addf(err, "Cannot lock the ref '%s'.", update->refname); - ret = 1; goto cleanup; } } @@ -3666,15 +3669,16 @@ int ref_transaction_commit(struct ref_transaction *transaction, struct ref_update *update = updates[i]; if (!is_null_sha1(update->new_sha1)) { - ret = write_ref_sha1(update->lock, update->new_sha1, - update->msg); - update->lock = NULL; /* freed by write_ref_sha1 */ - if (ret) { + if (write_ref_sha1(update->lock, update->new_sha1, + update->msg)) { + update->lock = NULL; /* freed by write_ref_sha1 */ if (err) strbuf_addf(err, "Cannot update the ref '%s'.", update->refname); + ret = TRANSACTION_GENERIC_ERROR; goto cleanup; } + update->lock = NULL; /* freed by write_ref_sha1 */ } } @@ -3683,14 +3687,16 @@ int ref_transaction_commit(struct ref_transaction *transaction, struct ref_update *update = updates[i]; if (update->lock) { - ret |= delete_ref_loose(update->lock, update->type, - err); + if (delete_ref_loose(update->lock, update->type, err)) + ret = TRANSACTION_GENERIC_ERROR; + if (!(update->flags & REF_ISPRUNING)) delnames[delnum++] = update->lock->ref_name; } } - ret |= repack_without_refs(delnames, delnum, err); + if (repack_without_refs(delnames, delnum, err)) + ret = TRANSACTION_GENERIC_ERROR; for (i = 0; i < delnum; i++) unlink_or_warn(git_path("logs/%s", delnames[i])); clear_loose_ref_cache(&ref_cache); diff --git a/refs.h b/refs.h index 1a55cabb4..50b115acc 100644 --- a/refs.h +++ b/refs.h @@ -326,9 +326,14 @@ int ref_transaction_delete(struct ref_transaction *transaction, /* * Commit all of the changes that have been queued in transaction, as - * atomically as possible. Return a nonzero value if there is a - * problem. + * atomically as possible. + * + * Returns 0 for success, or one of the below error codes for errors. */ +/* Naming conflict (for example, the ref names A and A/B conflict). */ +#define TRANSACTION_NAME_CONFLICT -1 +/* All other errors. */ +#define TRANSACTION_GENERIC_ERROR -2 int ref_transaction_commit(struct ref_transaction *transaction, struct strbuf *err);