mirror of
https://github.com/git/git.git
synced 2024-06-02 04:46:30 +02:00
refs: add a concept of a reference transaction
Build out the API for dealing with a bunch of reference checks and changes within a transaction. Define an opaque ref_transaction type that is managed entirely within refs.c. Introduce functions for beginning a transaction, adding updates to a transaction, and committing/rolling back a transaction. This API will soon replace update_refs(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
f11b09fb60
commit
caa4046c4f
99
refs.c
99
refs.c
|
@ -3267,6 +3267,96 @@ static int update_ref_write(const char *action, const char *refname,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data structure for holding a reference transaction, which can
|
||||||
|
* consist of checks and updates to multiple references, carried out
|
||||||
|
* as atomically as possible. This structure is opaque to callers.
|
||||||
|
*/
|
||||||
|
struct ref_transaction {
|
||||||
|
struct ref_update **updates;
|
||||||
|
size_t alloc;
|
||||||
|
size_t nr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ref_transaction *ref_transaction_begin(void)
|
||||||
|
{
|
||||||
|
return xcalloc(1, sizeof(struct ref_transaction));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ref_transaction_free(struct ref_transaction *transaction)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < transaction->nr; i++) {
|
||||||
|
struct ref_update *update = transaction->updates[i];
|
||||||
|
|
||||||
|
free((char *)update->ref_name);
|
||||||
|
free(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(transaction->updates);
|
||||||
|
free(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref_transaction_rollback(struct ref_transaction *transaction)
|
||||||
|
{
|
||||||
|
ref_transaction_free(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ref_update *add_update(struct ref_transaction *transaction,
|
||||||
|
const char *refname)
|
||||||
|
{
|
||||||
|
struct ref_update *update = xcalloc(1, sizeof(*update));
|
||||||
|
|
||||||
|
update->ref_name = xstrdup(refname);
|
||||||
|
ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
|
||||||
|
transaction->updates[transaction->nr++] = update;
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref_transaction_update(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *new_sha1, unsigned char *old_sha1,
|
||||||
|
int flags, int have_old)
|
||||||
|
{
|
||||||
|
struct ref_update *update = add_update(transaction, refname);
|
||||||
|
|
||||||
|
hashcpy(update->new_sha1, new_sha1);
|
||||||
|
update->flags = flags;
|
||||||
|
update->have_old = have_old;
|
||||||
|
if (have_old)
|
||||||
|
hashcpy(update->old_sha1, old_sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref_transaction_create(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *new_sha1,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct ref_update *update = add_update(transaction, refname);
|
||||||
|
|
||||||
|
assert(!is_null_sha1(new_sha1));
|
||||||
|
hashcpy(update->new_sha1, new_sha1);
|
||||||
|
hashclr(update->old_sha1);
|
||||||
|
update->flags = flags;
|
||||||
|
update->have_old = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref_transaction_delete(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *old_sha1,
|
||||||
|
int flags, int have_old)
|
||||||
|
{
|
||||||
|
struct ref_update *update = add_update(transaction, refname);
|
||||||
|
|
||||||
|
update->flags = flags;
|
||||||
|
update->have_old = have_old;
|
||||||
|
if (have_old) {
|
||||||
|
assert(!is_null_sha1(old_sha1));
|
||||||
|
hashcpy(update->old_sha1, old_sha1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int update_ref(const char *action, const char *refname,
|
int update_ref(const char *action, const char *refname,
|
||||||
const unsigned char *sha1, const unsigned char *oldval,
|
const unsigned char *sha1, const unsigned char *oldval,
|
||||||
int flags, enum action_on_err onerr)
|
int flags, enum action_on_err onerr)
|
||||||
|
@ -3378,6 +3468,15 @@ int update_refs(const char *action, struct ref_update * const *updates_orig,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ref_transaction_commit(struct ref_transaction *transaction,
|
||||||
|
const char *msg, enum action_on_err onerr)
|
||||||
|
{
|
||||||
|
int ret = update_refs(msg, transaction->updates, transaction->nr,
|
||||||
|
onerr);
|
||||||
|
ref_transaction_free(transaction);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
char *shorten_unambiguous_ref(const char *refname, int strict)
|
char *shorten_unambiguous_ref(const char *refname, int strict)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
65
refs.h
65
refs.h
|
@ -24,6 +24,8 @@ struct ref_update {
|
||||||
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
|
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ref_transaction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bit values set in the flags argument passed to each_ref_fn():
|
* Bit values set in the flags argument passed to each_ref_fn():
|
||||||
*/
|
*/
|
||||||
|
@ -220,6 +222,69 @@ enum action_on_err {
|
||||||
UPDATE_REFS_QUIET_ON_ERR
|
UPDATE_REFS_QUIET_ON_ERR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin a reference transaction. The reference transaction must
|
||||||
|
* eventually be commited using ref_transaction_commit() or rolled
|
||||||
|
* back using ref_transaction_rollback().
|
||||||
|
*/
|
||||||
|
struct ref_transaction *ref_transaction_begin(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Roll back a ref_transaction and free all associated data.
|
||||||
|
*/
|
||||||
|
void ref_transaction_rollback(struct ref_transaction *transaction);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following functions add a reference check or update to a
|
||||||
|
* ref_transaction. In all of them, refname is the name of the
|
||||||
|
* reference to be affected. The functions make internal copies of
|
||||||
|
* refname, so the caller retains ownership of the parameter. flags
|
||||||
|
* can be REF_NODEREF; it is passed to update_ref_lock().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a reference update to transaction. new_sha1 is the value that
|
||||||
|
* the reference should have after the update, or zeros if it should
|
||||||
|
* be deleted. If have_old is true, then old_sha1 holds the value
|
||||||
|
* that the reference should have had before the update, or zeros if
|
||||||
|
* it must not have existed beforehand.
|
||||||
|
*/
|
||||||
|
void ref_transaction_update(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *new_sha1, unsigned char *old_sha1,
|
||||||
|
int flags, int have_old);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a reference creation to transaction. new_sha1 is the value
|
||||||
|
* that the reference should have after the update; it must not be the
|
||||||
|
* null SHA-1. It is verified that the reference does not exist
|
||||||
|
* already.
|
||||||
|
*/
|
||||||
|
void ref_transaction_create(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *new_sha1,
|
||||||
|
int flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a reference deletion to transaction. If have_old is true, then
|
||||||
|
* old_sha1 holds the value that the reference should have had before
|
||||||
|
* the update (which must not be the null SHA-1).
|
||||||
|
*/
|
||||||
|
void ref_transaction_delete(struct ref_transaction *transaction,
|
||||||
|
const char *refname,
|
||||||
|
unsigned char *old_sha1,
|
||||||
|
int flags, int have_old);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Commit all of the changes that have been queued in transaction, as
|
||||||
|
* atomically as possible. Return a nonzero value if there is a
|
||||||
|
* problem. The ref_transaction is freed by this function.
|
||||||
|
*/
|
||||||
|
int ref_transaction_commit(struct ref_transaction *transaction,
|
||||||
|
const char *msg, enum action_on_err onerr);
|
||||||
|
|
||||||
/** Lock a ref and then write its file */
|
/** Lock a ref and then write its file */
|
||||||
int update_ref(const char *action, const char *refname,
|
int update_ref(const char *action, const char *refname,
|
||||||
const unsigned char *sha1, const unsigned char *oldval,
|
const unsigned char *sha1, const unsigned char *oldval,
|
||||||
|
|
Loading…
Reference in New Issue