summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Beller <sbeller@google.com>2015-01-08 03:23:19 (GMT)
committerJunio C Hamano <gitster@pobox.com>2015-01-08 03:56:43 (GMT)
commit68deed298ac4c257cd72d6bee543f651cb10d669 (patch)
treecc7b377b341e463b18c0a6efb76605f273819977
parent222368c6456211a3b2054ce4651cb58703886965 (diff)
downloadgit-68deed298ac4c257cd72d6bee543f651cb10d669.zip
git-68deed298ac4c257cd72d6bee543f651cb10d669.tar.gz
git-68deed298ac4c257cd72d6bee543f651cb10d669.tar.bz2
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>
-rw-r--r--builtin/receive-pack.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 96e56a7..362d33f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -40,6 +40,7 @@ static int transfer_unpack_limit = -1;
static int unpack_limit = 100;
static int report_status;
static int use_sideband;
+static int use_atomic;
static int quiet;
static int prefer_ofs_delta = 1;
static int auto_update_server_info;
@@ -1095,7 +1096,48 @@ static void execute_commands_non_atomic(struct command *commands,
}
ref_transaction_free(transaction);
}
+ strbuf_release(&err);
+}
+
+static void execute_commands_atomic(struct command *commands,
+ struct shallow_info *si)
+{
+ struct command *cmd;
+ struct strbuf err = STRBUF_INIT;
+ const char *reported_error = "atomic push failure";
+
+ transaction = ref_transaction_begin(&err);
+ if (!transaction) {
+ rp_error("%s", err.buf);
+ strbuf_reset(&err);
+ reported_error = "transaction failed to start";
+ goto failure;
+ }
+
+ for (cmd = commands; cmd; cmd = cmd->next) {
+ if (!should_process_cmd(cmd))
+ continue;
+
+ cmd->error_string = update(cmd, si);
+
+ if (cmd->error_string)
+ goto failure;
+ }
+ if (ref_transaction_commit(transaction, &err)) {
+ rp_error("%s", err.buf);
+ reported_error = "atomic transaction failed";
+ goto failure;
+ }
+ goto cleanup;
+
+failure:
+ for (cmd = commands; cmd; cmd = cmd->next)
+ if (!cmd->error_string)
+ cmd->error_string = reported_error;
+
+cleanup:
+ ref_transaction_free(transaction);
strbuf_release(&err);
}
@@ -1133,7 +1175,10 @@ static void execute_commands(struct command *commands,
free(head_name_to_free);
head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL);
- execute_commands_non_atomic(commands, si);
+ if (use_atomic)
+ execute_commands_atomic(commands, si);
+ else
+ execute_commands_non_atomic(commands, si);
if (shallow_update)
warn_if_skipped_connectivity_check(commands, si);