receive-pack.c: add execute_commands_atomic function
This introduces the new function execute_commands_atomic which will use one atomic transaction for all updates. The default behavior is still the old non atomic way, one ref at a time. This is to cause as little disruption as possible to existing clients. It is unknown if there are client scripts that depend on the old non-atomic behavior so we make it opt-in for now. A later patch will add the possibility to actually use the functionality added by this patch. For now use_atomic is always 0. Inspired-by: Ronnie Sahlberg <sahlberg@google.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stefan Beller committed
Jan 7, 2015 at 19:23 UTC
68deed298ac4c257cd72d6bee543f651cb10d669
1 file changed
+46
-1
builtin/receive-pack.c
+46
-1
@@ -40,6 +40,7 @@ static int transfer_unpack_limit = -1;
40
static int unpack_limit = 100;
41
static int report_status;
42
static int use_sideband;
43
+static int use_atomic;
44
static int quiet;
45
static int prefer_ofs_delta = 1;
46
static int auto_update_server_info;
@@ -1095,7 +1096,48 @@ static void execute_commands_non_atomic(struct command *commands,
1096
}
1097
ref_transaction_free(transaction);
1098
}
1099
+ strbuf_release(&err);
1100
+}
1101
+
1102
+static void execute_commands_atomic(struct command *commands,
1103
+ struct shallow_info *si)
1104
+{
1105
+ struct command *cmd;
1106
+ struct strbuf err = STRBUF_INIT;
1107
+ const char *reported_error = "atomic push failure";
1108
+
1109
+ transaction = ref_transaction_begin(&err);
1110
+ if (!transaction) {
1111
+ rp_error("%s", err.buf);
1112
+ strbuf_reset(&err);
1113
+ reported_error = "transaction failed to start";
1114
+ goto failure;
1115
+ }
1116
+
1117
+ for (cmd = commands; cmd; cmd = cmd->next) {
1118
+ if (!should_process_cmd(cmd))
1119
+ continue;
1120
+
1121
+ cmd->error_string = update(cmd, si);
1122
+
1123
+ if (cmd->error_string)
1124
+ goto failure;
1125
+ }
1126
1127
+ if (ref_transaction_commit(transaction, &err)) {
1128
+ rp_error("%s", err.buf);
1129
+ reported_error = "atomic transaction failed";
1130
+ goto failure;
1131
+ }
1132
+ goto cleanup;
1133
+
1134
+failure:
1135
+ for (cmd = commands; cmd; cmd = cmd->next)
1136
+ if (!cmd->error_string)
1137
+ cmd->error_string = reported_error;
1138
+
1139
+cleanup:
1140
+ ref_transaction_free(transaction);
1141
strbuf_release(&err);
1142
}
1143
@@ -1133,7 +1175,10 @@ static void execute_commands(struct command *commands,
1175
free(head_name_to_free);
1176
head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL);
1177
1136
- execute_commands_non_atomic(commands, si);
1178
+ if (use_atomic)
1179
+ execute_commands_atomic(commands, si);
1180
+ else
1181
+ execute_commands_non_atomic(commands, si);
1182
1183
if (shallow_update)
1184
warn_if_skipped_connectivity_check(commands, si);