Add receive.preferatomicpush setting to receive-pack.c. This triggers a new capability "prefer-atomic-push" to be sent back to the send-pack client, requesting the client, if it supports it, to request an atomic push. This is an alternative way to trigger an atomic push instead of having to rely of the user using the --atomic-push command line argument. For backward compatibility, this is only a hint to the client that is should request atomic pushes if it can. Old clients that do not support atomic pushes will just ignore this capability and use a normal push. The reason we need to signal this capability back to the client is due to that send_pack() has push failure modes where it will detect that certain refs can not be pushed and fail them early. Those refs would not even be sent by the client unless atomic-pushes are activated. This means that IF we activate this feature from the server side we must tell the client to not fail refs early and use an atomic push. We can not enforce this on the server side only. Change-Id: I6677cd565f48a09bb552fe3f4c00bbb6d343c224 Signed-off-by: Ronnie Sahlberg <sahlberg@xxxxxxxxxx> --- Documentation/config.txt | 4 +++ Documentation/technical/protocol-capabilities.txt | 13 ++++++--- builtin/receive-pack.c | 8 ++++++ send-pack.c | 2 ++ t/t5543-atomic-push.sh | 32 +++++++++++++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 400dcad..78c427e 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2135,6 +2135,10 @@ receive.shallowupdate:: If set to true, .git/shallow can be updated when new refs require new shallow roots. Otherwise those refs are rejected. +receive.preferatomicpush:: + This option is used in receive-pack to tell the client to try + to use an atomic push, if the client supports it. + remote.pushdefault:: The remote to push to by default. Overrides `branch.<name>.remote` for all branches, and is overridden by diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt index 26bc5b1..78c5469 100644 --- a/Documentation/technical/protocol-capabilities.txt +++ b/Documentation/technical/protocol-capabilities.txt @@ -18,9 +18,9 @@ was sent. Server MUST NOT ignore capabilities that client requested and server advertised. As a consequence of these rules, server MUST NOT advertise capabilities it does not understand. -The 'atomic-push', 'report-status', 'delete-refs', 'quiet', and 'push-cert' -capabilities are sent and recognized by the receive-pack (push to server) -process. +The 'atomic-push', 'report-status', 'delete-refs', 'prefer-atomic-push', +'quiet', and 'push-cert' capabilities are sent and recognized by the +receive-pack (push to server) process. The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized by both upload-pack and receive-pack protocols. The 'agent' capability @@ -252,6 +252,13 @@ If the server sends the 'atomic-push' capability, it means it is capable of accepting atomic pushes. If the pushing client requests this capability, the server will update the refs in one single atomic transaction. +prefer-atomic-push +------------------ + +If the receive-pack server advertises the 'prefer-atomic-push' capability, +it means that the client should use an atomic push, if the client supports it, +even if the user did not request it explicitly. + allow-tip-sha1-in-want ---------------------- diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 6991d22..697f102 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -52,6 +52,7 @@ static const char *head_name; static void *head_name_to_free; static int sent_capabilities; static int shallow_update; +static int prefer_atomic_push; static const char *alt_shallow_file; static struct strbuf push_cert = STRBUF_INIT; static unsigned char push_cert_sha1[20]; @@ -160,6 +161,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } + if (strcmp(var, "receive.preferatomicpush") == 0) { + prefer_atomic_push = git_config_bool(var, value); + return 0; + } + return git_default_config(var, value, cb); } @@ -178,6 +184,8 @@ static void show_ref(const char *path, const unsigned char *sha1) "atomic-push"); if (prefer_ofs_delta) strbuf_addstr(&cap, " ofs-delta"); + if (prefer_atomic_push) + strbuf_addstr(&cap, " prefer-atomic-push"); if (push_cert_nonce) strbuf_addf(&cap, " push-cert=%s", push_cert_nonce); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); diff --git a/send-pack.c b/send-pack.c index 5208305..c5e0539 100644 --- a/send-pack.c +++ b/send-pack.c @@ -325,6 +325,8 @@ int send_pack(struct send_pack_args *args, args->use_thin_pack = 0; if (server_supports("atomic-push")) atomic_push_supported = 1; + if (server_supports("prefer-atomic-push")) + args->use_atomic_push = 1; if (args->push_cert) { int len; diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 4903227..3feb22e 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -98,4 +98,36 @@ test_expect_success 'atomic push fails if one branch fails' ' test "$master_second" != "$mirror_second" ' +test_expect_success 'atomic push fails (receive.preferatomicpush)' ' + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git branch second && + git checkout second && + echo two >foo && git add foo && git commit -m two && + echo three >foo && git add foo && git commit -m three && + echo four >foo && git add foo && git commit -m four && + git push --mirror up + git reset --hard HEAD~2 && + git checkout master + echo five >foo && git add foo && git commit -m five + ) && + ( + cd mirror && + git config --add receive.preferatomicpush true + ) && + ( + cd master && + ! git push --atomic-push --all up + ) && + master_master=$(cd master && git show-ref -s --verify refs/heads/master) && + mirror_master=$(cd mirror && git show-ref -s --verify refs/heads/master) && + test "$master_master" != "$mirror_master" && + + master_second=$(cd master && git show-ref -s --verify refs/heads/second) && + mirror_second=$(cd mirror && git show-ref -s --verify refs/heads/second) && + test "$master_second" != "$mirror_second" +' + test_done -- 2.1.0.rc2.206.gedb03e5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html