diff --git a/refs.c b/refs.c
index a82d6ba..206e1a2 100644
--- a/refs.c
+++ b/refs.c
@@ -3288,6 +3288,12 @@ struct ref_update {
const char refname[FLEX_ARRAY];
};
+enum ref_transaction_status {
+ REF_TRANSACTION_OPEN = 0,
+ REF_TRANSACTION_CLOSED = 1,
+ REF_TRANSACTION_ERROR = 2,
+};
+
/*
* Data structure for holding a reference transaction, which can
* consist of checks and updates to multiple references, carried out@@ -3297,6 +3303,7 @@ struct ref_transaction {
struct ref_update **updates;
size_t alloc;
size_t nr;
+ enum ref_transaction_status status;
};
struct ref_transaction *ref_transaction_begin(void)@@ -3320,6 +3327,11 @@ void ref_transaction_free(struct ref_transaction *transaction)
void ref_transaction_rollback(struct ref_transaction *transaction)
{
+ if (!transaction)
+ return;
+
+ transaction->status = REF_TRANSACTION_ERROR;
+
ref_transaction_free(transaction);
}
@@ -3344,7 +3356,10 @@ int ref_transaction_update(struct ref_transaction *transaction,
struct ref_update *update;
if (have_old && !old_sha1)
- die("have_old is true but old_sha1 is NULL");
+ die("BUG: have_old is true but old_sha1 is NULL");
+
+ if (transaction->status != REF_TRANSACTION_OPEN)
+ die("BUG: update on transaction that is not open");
update = add_update(transaction, refname);
hashcpy(update->new_sha1, new_sha1);@@ -3363,7 +3378,10 @@ int ref_transaction_create(struct ref_transaction *transaction,
struct ref_update *update;
if (!new_sha1 || is_null_sha1(new_sha1))
- die("create ref with null new_sha1");
+ die("BUG: create ref with null new_sha1");
+
+ if (transaction->status != REF_TRANSACTION_OPEN)
+ die("BUG: create on transaction that is not open");
update = add_update(transaction, refname);
@@ -3382,7 +3400,10 @@ int ref_transaction_delete(struct ref_transaction *transaction,
struct ref_update *update;
if (have_old && !old_sha1)
- die("have_old is true but old_sha1 is NULL");
+ die("BUG: have_old is true but old_sha1 is NULL");
+
+ if (transaction->status != REF_TRANSACTION_OPEN)
+ die("BUG: delete on transaction that is not open");
update = add_update(transaction, refname);
update->flags = flags;@@ -3454,8 +3475,13 @@ int ref_transaction_commit(struct ref_transaction *transaction,
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
- if (!n)
+ if (transaction->status != REF_TRANSACTION_OPEN)
+ die("BUG: commit on transaction that is not open");
+
+ if (!n) {
+ transaction->status = REF_TRANSACTION_CLOSED;
return 0;
+ }
/* Allocate work space */
delnames = xmalloc(sizeof(*delnames) * n);@@ -3517,6 +3543,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
clear_loose_ref_cache(&ref_cache);
cleanup:
+ transaction->status = ret ? REF_TRANSACTION_ERROR
+ : REF_TRANSACTION_CLOSED;
+
for (i = 0; i < n; i++)
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
--
1.9.1.532.gf8485a6