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 */