refs.c: change ref_transaction_create to do error checking and return status

Do basic error checking in ref_transaction_create() and make it return
non-zero on error. Update all callers to check the result of
ref_transaction_create(). There are currently no conditions in _create that
will return error but there will be in the future. Add an err argument that
will be updated on failure.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ronnie Sahlberg 2014-04-16 15:26:44 -07:00 коммит произвёл Junio C Hamano
Родитель 8e34800e5b
Коммит b416af5bcd
3 изменённых файлов: 56 добавлений и 14 удалений

Просмотреть файл

@ -226,7 +226,9 @@ static const char *parse_cmd_create(struct strbuf *input, const char *next)
if (*next != line_termination) if (*next != line_termination)
die("create %s: extra input: %s", refname, next); die("create %s: extra input: %s", refname, next);
ref_transaction_create(transaction, refname, new_sha1, update_flags); if (ref_transaction_create(transaction, refname, new_sha1,
update_flags, &err))
die("%s", err.buf);
update_flags = 0; update_flags = 0;
free(refname); free(refname);

18
refs.c
Просмотреть файл

@ -3449,18 +3449,24 @@ int ref_transaction_update(struct ref_transaction *transaction,
return 0; return 0;
} }
void ref_transaction_create(struct ref_transaction *transaction, int ref_transaction_create(struct ref_transaction *transaction,
const char *refname, const char *refname,
const unsigned char *new_sha1, const unsigned char *new_sha1,
int flags) int flags,
struct strbuf *err)
{ {
struct ref_update *update = add_update(transaction, refname); struct ref_update *update;
if (!new_sha1 || is_null_sha1(new_sha1))
die("BUG: create ref with null new_sha1");
update = add_update(transaction, refname);
assert(!is_null_sha1(new_sha1));
hashcpy(update->new_sha1, new_sha1); hashcpy(update->new_sha1, new_sha1);
hashclr(update->old_sha1); hashclr(update->old_sha1);
update->flags = flags; update->flags = flags;
update->have_old = 1; update->have_old = 1;
return 0;
} }
void ref_transaction_delete(struct ref_transaction *transaction, void ref_transaction_delete(struct ref_transaction *transaction,

48
refs.h
Просмотреть файл

@ -10,6 +10,38 @@ struct ref_lock {
int force_write; int force_write;
}; };
/*
* A ref_transaction represents a collection of ref updates
* that should succeed or fail together.
*
* Calling sequence
* ----------------
* - Allocate and initialize a `struct ref_transaction` by calling
* `ref_transaction_begin()`.
*
* - List intended ref updates by calling functions like
* `ref_transaction_update()` and `ref_transaction_create()`.
*
* - Call `ref_transaction_commit()` to execute the transaction.
* If this succeeds, the ref updates will have taken place and
* the transaction cannot be rolled back.
*
* - At any time call `ref_transaction_free()` to discard the
* transaction and free associated resources. In particular,
* this rolls back the transaction if it has not been
* successfully committed.
*
* Error handling
* --------------
*
* On error, transaction functions append a message about what
* went wrong to the 'err' argument. The message mentions what
* ref was being updated (if any) when the error occurred so it
* can be passed to 'die' or 'error' as-is.
*
* The message is appended to err without first clearing err.
* err will not be '\n' terminated.
*/
struct ref_transaction; struct ref_transaction;
/* /*
@ -248,7 +280,7 @@ struct ref_transaction *ref_transaction_begin(void);
* it must not have existed beforehand. * it must not have existed beforehand.
* Function returns 0 on success and non-zero on failure. A failure to update * Function returns 0 on success and non-zero on failure. A failure to update
* means that the transaction as a whole has failed and will need to be * means that the transaction as a whole has failed and will need to be
* rolled back. On failure the err buffer will be updated. * rolled back.
*/ */
int ref_transaction_update(struct ref_transaction *transaction, int ref_transaction_update(struct ref_transaction *transaction,
const char *refname, const char *refname,
@ -262,11 +294,15 @@ int ref_transaction_update(struct ref_transaction *transaction,
* that the reference should have after the update; it must not be the * 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 * null SHA-1. It is verified that the reference does not exist
* already. * already.
* Function returns 0 on success and non-zero on failure. A failure to create
* means that the transaction as a whole has failed and will need to be
* rolled back.
*/ */
void ref_transaction_create(struct ref_transaction *transaction, int ref_transaction_create(struct ref_transaction *transaction,
const char *refname, const char *refname,
const unsigned char *new_sha1, const unsigned char *new_sha1,
int flags); int flags,
struct strbuf *err);
/* /*
* Add a reference deletion to transaction. If have_old is true, then * Add a reference deletion to transaction. If have_old is true, then
@ -282,8 +318,6 @@ void ref_transaction_delete(struct ref_transaction *transaction,
* Commit all of the changes that have been queued in transaction, as * Commit all of the changes that have been queued in transaction, as
* atomically as possible. Return a nonzero value if there is a * atomically as possible. Return a nonzero value if there is a
* problem. * problem.
* If err is non-NULL we will add an error string to it to explain why
* the transaction failed. The string does not end in newline.
*/ */
int ref_transaction_commit(struct ref_transaction *transaction, int ref_transaction_commit(struct ref_transaction *transaction,
const char *msg, struct strbuf *err); const char *msg, struct strbuf *err);