diff --git a/refs.c b/refs.c
index ec8d642..6414afc 100644
--- a/refs.c
+++ b/refs.c
@@ -3504,7 +3504,7 @@ static int ref_update_reject_duplicates(struct ref_update **updates, int n,
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- int ret = 0, delnum = 0, i;
+ int ret = 0, delnum = 0, i, save_errno = 0;
const char **delnames;
int n = transaction->nr;
struct ref_update **updates = transaction->updates;@@ -3522,9 +3522,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 = -1;
goto cleanup;
+ }
/* Acquire all locks while verifying old values */
for (i = 0; i < n; i++) {@@ -3538,10 +3539,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
&update->type,
delnames, delnum);
if (!update->lock) {
+ if (errno == ENOTDIR)
+ save_errno = errno;
if (err)
strbuf_addf(err, "Cannot lock the ref '%s'.",
update->refname);
- ret = 1;
+ ret = -1;
goto cleanup;
}
}@@ -3559,6 +3562,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (err)
strbuf_addf(err, str, update->refname);
+ ret = -1;
goto cleanup;
}
}
@@ -3569,14 +3573,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 = -1;
+
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 = -1;
for (i = 0; i < delnum; i++)
unlink_or_warn(git_path("logs/%s", delnames[i]));
clear_loose_ref_cache(&ref_cache);@@ -3589,6 +3595,9 @@ cleanup:
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
free(delnames);
+ errno = save_errno;
+ if (save_errno == ENOTDIR)
+ ret = -2;
return ret;
}
diff --git a/refs.h b/refs.h
index 5c6c20f..88732a1 100644
--- a/refs.h
+++ b/refs.h
@@ -323,6 +323,10 @@ 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.
+ * If the transaction is already in failed state this function will return
+ * an error.
+ * Function returns 0 on success, -1 for generic failures and -2 if the
+ * failure was due to a name collision (ENOTDIR).
*/
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err);
--
2.0.0.rc3.474.g3833130