Skip to content

Commit 28e6a97

Browse files
rsahlberggitster
authored andcommitted
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 <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5fe7d82 commit 28e6a97

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

refs.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,9 +3637,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
36373637

36383638
/* Copy, sort, and reject duplicate refs */
36393639
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;
36423642
goto cleanup;
3643+
}
36433644

36443645
/* Acquire all locks while verifying old values */
36453646
for (i = 0; i < n; i++) {
@@ -3653,10 +3654,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
36533654
update->flags,
36543655
&update->type);
36553656
if (!update->lock) {
3657+
ret = (errno == ENOTDIR)
3658+
? TRANSACTION_NAME_CONFLICT
3659+
: TRANSACTION_GENERIC_ERROR;
36563660
if (err)
36573661
strbuf_addf(err, "Cannot lock the ref '%s'.",
36583662
update->refname);
3659-
ret = 1;
36603663
goto cleanup;
36613664
}
36623665
}
@@ -3666,15 +3669,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
36663669
struct ref_update *update = updates[i];
36673670

36683671
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 */
36733675
if (err)
36743676
strbuf_addf(err, "Cannot update the ref '%s'.",
36753677
update->refname);
3678+
ret = TRANSACTION_GENERIC_ERROR;
36763679
goto cleanup;
36773680
}
3681+
update->lock = NULL; /* freed by write_ref_sha1 */
36783682
}
36793683
}
36803684

@@ -3683,14 +3687,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
36833687
struct ref_update *update = updates[i];
36843688

36853689
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+
36883693
if (!(update->flags & REF_ISPRUNING))
36893694
delnames[delnum++] = update->lock->ref_name;
36903695
}
36913696
}
36923697

3693-
ret |= repack_without_refs(delnames, delnum, err);
3698+
if (repack_without_refs(delnames, delnum, err))
3699+
ret = TRANSACTION_GENERIC_ERROR;
36943700
for (i = 0; i < delnum; i++)
36953701
unlink_or_warn(git_path("logs/%s", delnames[i]));
36963702
clear_loose_ref_cache(&ref_cache);

refs.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,14 @@ int ref_transaction_delete(struct ref_transaction *transaction,
326326

327327
/*
328328
* 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.
331332
*/
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
332337
int ref_transaction_commit(struct ref_transaction *transaction,
333338
struct strbuf *err);
334339

0 commit comments

Comments
 (0)