lock_ref_for_update(): new function

Extract a new function, lock_ref_for_update(), from ref_transaction_commit(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>

Michael Haggerty committed Apr 24, 2016 at 08:58 UTC 165056b2fc065e27e4077a11ed2bf1589207b997
1 file changed +85 -67
refs/files-backend.c
+85 -67
@@ -3051,6 +3051,88 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
3051 return 0;
3052 }
3053
3054 +/*
3055 + * Acquire all locks, verify old values if provided, check
3056 + * that new values are valid, and write new values to the
3057 + * lockfiles, ready to be activated. Only keep one lockfile
3058 + * open at a time to avoid running out of file descriptors.
3059 + */
3060 +static int lock_ref_for_update(struct ref_update *update,
3061 + struct ref_transaction *transaction,
3062 + struct string_list *affected_refnames,
3063 + struct strbuf *err)
3064 +{
3065 + int ret;
3066 +
3067 + if ((update->flags & REF_HAVE_NEW) &&
3068 + is_null_sha1(update->new_sha1))
3069 + update->flags |= REF_DELETING;
3070 + update->lock = lock_ref_sha1_basic(
3071 + update->refname,
3072 + ((update->flags & REF_HAVE_OLD) ?
3073 + update->old_sha1 : NULL),
3074 + affected_refnames, NULL,
3075 + update->flags,
3076 + &update->type,
3077 + err);
3078 + if (!update->lock) {
3079 + char *reason;
3080 +
3081 + ret = (errno == ENOTDIR)
3082 + ? TRANSACTION_NAME_CONFLICT
3083 + : TRANSACTION_GENERIC_ERROR;
3084 + reason = strbuf_detach(err, NULL);
3085 + strbuf_addf(err, "cannot lock ref '%s': %s",
3086 + update->refname, reason);
3087 + free(reason);
3088 + return ret;
3089 + }
3090 + if ((update->flags & REF_HAVE_NEW) &&
3091 + !(update->flags & REF_DELETING) &&
3092 + !(update->flags & REF_LOG_ONLY)) {
3093 + int overwriting_symref = ((update->type & REF_ISSYMREF) &&
3094 + (update->flags & REF_NODEREF));
3095 +
3096 + if (!overwriting_symref &&
3097 + !hashcmp(update->lock->old_oid.hash, update->new_sha1)) {
3098 + /*
3099 + * The reference already has the desired
3100 + * value, so we don't need to write it.
3101 + */
3102 + } else if (write_ref_to_lockfile(update->lock,
3103 + update->new_sha1,
3104 + err)) {
3105 + char *write_err = strbuf_detach(err, NULL);
3106 +
3107 + /*
3108 + * The lock was freed upon failure of
3109 + * write_ref_to_lockfile():
3110 + */
3111 + update->lock = NULL;
3112 + strbuf_addf(err,
3113 + "cannot update the ref '%s': %s",
3114 + update->refname, write_err);
3115 + free(write_err);
3116 + return TRANSACTION_GENERIC_ERROR;
3117 + } else {
3118 + update->flags |= REF_NEEDS_COMMIT;
3119 + }
3120 + }
3121 + if (!(update->flags & REF_NEEDS_COMMIT)) {
3122 + /*
3123 + * We didn't call write_ref_to_lockfile(), so
3124 + * the lockfile is still open. Close it to
3125 + * free up the file descriptor:
3126 + */
3127 + if (close_ref(update->lock)) {
3128 + strbuf_addf(err, "couldn't close '%s.lock'",
3129 + update->refname);
3130 + return TRANSACTION_GENERIC_ERROR;
3131 + }
3132 + }
3133 + return 0;
3134 +}
3135 +
3136 int ref_transaction_commit(struct ref_transaction *transaction,
3137 struct strbuf *err)
3138 {
@@ -3088,74 +3170,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
3170 for (i = 0; i < transaction->nr; i++) {
3171 struct ref_update *update = transaction->updates[i];
3172
3091 - if ((update->flags & REF_HAVE_NEW) &&
3092 - is_null_sha1(update->new_sha1))
3093 - update->flags |= REF_DELETING;
3094 - update->lock = lock_ref_sha1_basic(
3095 - update->refname,
3096 - ((update->flags & REF_HAVE_OLD) ?
3097 - update->old_sha1 : NULL),
3098 - &affected_refnames, NULL,
3099 - update->flags,
3100 - &update->type,
3101 - err);
3102 - if (!update->lock) {
3103 - char *reason;
3104 -
3105 - ret = (errno == ENOTDIR)
3106 - ? TRANSACTION_NAME_CONFLICT
3107 - : TRANSACTION_GENERIC_ERROR;
3108 - reason = strbuf_detach(err, NULL);
3109 - strbuf_addf(err, "cannot lock ref '%s': %s",
3110 - update->refname, reason);
3111 - free(reason);
3173 + ret = lock_ref_for_update(update, transaction,
3174 + &affected_refnames, err);
3175 + if (ret)
3176 goto cleanup;
3113 - }
3114 - if ((update->flags & REF_HAVE_NEW) &&
3115 - !(update->flags & REF_DELETING) &&
3116 - !(update->flags & REF_LOG_ONLY)) {
3117 - int overwriting_symref = ((update->type & REF_ISSYMREF) &&
3118 - (update->flags & REF_NODEREF));
3119 -
3120 - if (!overwriting_symref &&
3121 - !hashcmp(update->lock->old_oid.hash, update->new_sha1)) {
3122 - /*
3123 - * The reference already has the desired
3124 - * value, so we don't need to write it.
3125 - */
3126 - } else if (write_ref_to_lockfile(update->lock,
3127 - update->new_sha1,
3128 - err)) {
3129 - char *write_err = strbuf_detach(err, NULL);
3130 -
3131 - /*
3132 - * The lock was freed upon failure of
3133 - * write_ref_to_lockfile():
3134 - */
3135 - update->lock = NULL;
3136 - strbuf_addf(err,
3137 - "cannot update the ref '%s': %s",
3138 - update->refname, write_err);
3139 - free(write_err);
3140 - ret = TRANSACTION_GENERIC_ERROR;
3141 - goto cleanup;
3142 - } else {
3143 - update->flags |= REF_NEEDS_COMMIT;
3144 - }
3145 - }
3146 - if (!(update->flags & REF_NEEDS_COMMIT)) {
3147 - /*
3148 - * We didn't call write_ref_to_lockfile(), so
3149 - * the lockfile is still open. Close it to
3150 - * free up the file descriptor:
3151 - */
3152 - if (close_ref(update->lock)) {
3153 - strbuf_addf(err, "couldn't close '%s.lock'",
3154 - update->refname);
3155 - ret = TRANSACTION_GENERIC_ERROR;
3156 - goto cleanup;
3157 - }
3158 - }
3177 }
3178
3179 /* Perform updates first so live commits remain referenced */