diff options
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 47 |
1 files changed, 39 insertions, 8 deletions
@@ -47,10 +47,16 @@ static unsigned char refname_disposition[256] = { #define REF_ISPRUNING 0x04 /* + * Used as a flag in ref_update::flags when the reference should be + * updated to new_sha1. + */ +#define REF_HAVE_NEW 0x08 + +/* * Used as a flag in ref_update::flags when old_sha1 should be * checked. */ -#define REF_HAVE_OLD 0x08 +#define REF_HAVE_OLD 0x10 /* * Try to read one refname component from the front of refname. @@ -3577,10 +3583,17 @@ int for_each_reflog(each_ref_fn fn, void *cb_data) * not exist before update. */ struct ref_update { + /* + * If (flags & REF_HAVE_NEW), set the reference to this value: + */ unsigned char new_sha1[20]; + /* + * If (flags & REF_HAVE_OLD), check that the reference + * previously had this value: + */ unsigned char old_sha1[20]; /* - * One or more of REF_HAVE_OLD, REF_NODEREF, + * One or more of REF_HAVE_NEW, REF_HAVE_OLD, REF_NODEREF, * REF_DELETING, and REF_ISPRUNING: */ unsigned int flags; @@ -3665,7 +3678,7 @@ int ref_transaction_update(struct ref_transaction *transaction, if (transaction->state != REF_TRANSACTION_OPEN) die("BUG: update called for transaction that is not open"); - if (!is_null_sha1(new_sha1) && + if (new_sha1 && !is_null_sha1(new_sha1) && check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { strbuf_addf(err, "refusing to update ref with bad name %s", refname); @@ -3673,7 +3686,10 @@ int ref_transaction_update(struct ref_transaction *transaction, } update = add_update(transaction, refname); - hashcpy(update->new_sha1, new_sha1); + if (new_sha1) { + hashcpy(update->new_sha1, new_sha1); + flags |= REF_HAVE_NEW; + } if (old_sha1) { hashcpy(update->old_sha1, old_sha1); flags |= REF_HAVE_OLD; @@ -3709,6 +3725,19 @@ int ref_transaction_delete(struct ref_transaction *transaction, flags, msg, err); } +int ref_transaction_verify(struct ref_transaction *transaction, + const char *refname, + const unsigned char *old_sha1, + unsigned int flags, + struct strbuf *err) +{ + if (!old_sha1) + die("BUG: verify called with old_sha1 set to NULL"); + return ref_transaction_update(transaction, refname, + NULL, old_sha1, + flags, NULL, err); +} + int update_ref(const char *action, const char *refname, const unsigned char *sha1, const unsigned char *oldval, unsigned int flags, enum action_on_err onerr) @@ -3797,7 +3826,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, struct ref_update *update = updates[i]; unsigned int flags = update->flags; - if (is_null_sha1(update->new_sha1)) + if ((flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1)) flags |= REF_DELETING; update->lock = lock_ref_sha1_basic( update->refname, @@ -3819,8 +3848,9 @@ int ref_transaction_commit(struct ref_transaction *transaction, /* Perform updates first so live commits remain referenced */ for (i = 0; i < n; i++) { struct ref_update *update = updates[i]; + int flags = update->flags; - if (!is_null_sha1(update->new_sha1)) { + if ((flags & REF_HAVE_NEW) && !is_null_sha1(update->new_sha1)) { if (write_ref_sha1(update->lock, update->new_sha1, update->msg)) { update->lock = NULL; /* freed by write_ref_sha1 */ @@ -3836,14 +3866,15 @@ int ref_transaction_commit(struct ref_transaction *transaction, /* Perform deletes now that updates are safely completed */ for (i = 0; i < n; i++) { struct ref_update *update = updates[i]; + int flags = update->flags; - if (update->lock) { + if ((flags & REF_HAVE_NEW) && is_null_sha1(update->new_sha1)) { if (delete_ref_loose(update->lock, update->type, err)) { ret = TRANSACTION_GENERIC_ERROR; goto cleanup; } - if (!(update->flags & REF_ISPRUNING)) + if (!(flags & REF_ISPRUNING)) string_list_append(&refs_to_delete, update->lock->ref_name); } |