receive-pack: implement advertising and receiving push options

The pre/post receive hook may be interested in more information from the
user. This information can be transmitted when both client and server
support the "push-options" capability, which when used is a phase directly
after update commands ended by a flush pkt.

Similar to the atomic option, the server capability can be disabled via
the `receive.advertisePushOptions` config variable. While documenting
this, fix a nit in the `receive.advertiseAtomic` wording.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller
2016-07-14 14:49:46 -07:00
committed by Junio C Hamano
parent 77a9745d19
commit c714e45f87
4 changed files with 52 additions and 6 deletions

View File

@ -2410,8 +2410,13 @@ rebase.instructionFormat
receive.advertiseAtomic:: receive.advertiseAtomic::
By default, git-receive-pack will advertise the atomic push By default, git-receive-pack will advertise the atomic push
capability to its clients. If you don't want to this capability capability to its clients. If you don't want to advertise this
to be advertised, set this variable to false. capability, set this variable to false.
receive.advertisePushOptions::
By default, git-receive-pack will advertise the push options
capability to its clients. If you don't want to advertise this
capability, set this variable to false.
receive.autogc:: receive.autogc::
By default, git-receive-pack will run "git-gc --auto" after By default, git-receive-pack will run "git-gc --auto" after

View File

@ -454,7 +454,8 @@ The reference discovery phase is done nearly the same way as it is in the
fetching protocol. Each reference obj-id and name on the server is sent fetching protocol. Each reference obj-id and name on the server is sent
in packet-line format to the client, followed by a flush-pkt. The only in packet-line format to the client, followed by a flush-pkt. The only
real difference is that the capability listing is different - the only real difference is that the capability listing is different - the only
possible values are 'report-status', 'delete-refs' and 'ofs-delta'. possible values are 'report-status', 'delete-refs', 'ofs-delta' and
'push-options'.
Reference Update Request and Packfile Transfer Reference Update Request and Packfile Transfer
---------------------------------------------- ----------------------------------------------
@ -465,9 +466,10 @@ that it wants to update, it sends a line listing the obj-id currently on
the server, the obj-id the client would like to update it to and the name the server, the obj-id the client would like to update it to and the name
of the reference. of the reference.
This list is followed by a flush-pkt and then the packfile that should This list is followed by a flush-pkt. Then the push options are transmitted
contain all the objects that the server will need to complete the new one per packet followed by another flush-pkt. After that the packfile that
references. should contain all the objects that the server will need to complete the new
references will be sent.
---- ----
update-request = *shallow ( command-list | push-cert ) [packfile] update-request = *shallow ( command-list | push-cert ) [packfile]

View File

@ -253,6 +253,15 @@ atomic pushes. If the pushing client requests this capability, the server
will update the refs in one atomic transaction. Either all refs are will update the refs in one atomic transaction. Either all refs are
updated or none. updated or none.
push-options
------------
If the server sends the 'push-options' capability it is able to accept
push options after the update commands have been sent, but before the
packfile is streamed. If the pushing client requests this capability,
the server will pass the options to the pre- and post- receive hooks
that process this push request.
allow-tip-sha1-in-want allow-tip-sha1-in-want
---------------------- ----------------------

View File

@ -44,10 +44,12 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
static int receive_unpack_limit = -1; static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1; static int transfer_unpack_limit = -1;
static int advertise_atomic_push = 1; static int advertise_atomic_push = 1;
static int advertise_push_options;
static int unpack_limit = 100; static int unpack_limit = 100;
static int report_status; static int report_status;
static int use_sideband; static int use_sideband;
static int use_atomic; static int use_atomic;
static int use_push_options;
static int quiet; static int quiet;
static int prefer_ofs_delta = 1; static int prefer_ofs_delta = 1;
static int auto_update_server_info; static int auto_update_server_info;
@ -193,6 +195,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0; return 0;
} }
if (strcmp(var, "receive.advertisepushoptions") == 0) {
advertise_push_options = git_config_bool(var, value);
return 0;
}
return git_default_config(var, value, cb); return git_default_config(var, value, cb);
} }
@ -211,6 +218,8 @@ static void show_ref(const char *path, const unsigned char *sha1)
strbuf_addstr(&cap, " ofs-delta"); strbuf_addstr(&cap, " ofs-delta");
if (push_cert_nonce) if (push_cert_nonce)
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce); strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
if (advertise_push_options)
strbuf_addstr(&cap, " push-options");
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
packet_write(1, "%s %s%c%s\n", packet_write(1, "%s %s%c%s\n",
sha1_to_hex(sha1), path, 0, cap.buf); sha1_to_hex(sha1), path, 0, cap.buf);
@ -1455,6 +1464,9 @@ static struct command *read_head_info(struct sha1_array *shallow)
if (advertise_atomic_push if (advertise_atomic_push
&& parse_feature_request(feature_list, "atomic")) && parse_feature_request(feature_list, "atomic"))
use_atomic = 1; use_atomic = 1;
if (advertise_push_options
&& parse_feature_request(feature_list, "push-options"))
use_push_options = 1;
} }
if (!strcmp(line, "push-cert")) { if (!strcmp(line, "push-cert")) {
@ -1487,6 +1499,21 @@ static struct command *read_head_info(struct sha1_array *shallow)
return commands; return commands;
} }
static void read_push_options(struct string_list *options)
{
while (1) {
char *line;
int len;
line = packet_read_line(0, &len);
if (!line)
break;
string_list_append(options, line);
}
}
static const char *parse_pack_header(struct pack_header *hdr) static const char *parse_pack_header(struct pack_header *hdr)
{ {
switch (read_pack_header(0, hdr)) { switch (read_pack_header(0, hdr)) {
@ -1774,6 +1801,9 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
const char *unpack_status = NULL; const char *unpack_status = NULL;
struct string_list push_options = STRING_LIST_INIT_DUP; struct string_list push_options = STRING_LIST_INIT_DUP;
if (use_push_options)
read_push_options(&push_options);
prepare_shallow_info(&si, &shallow); prepare_shallow_info(&si, &shallow);
if (!si.nr_ours && !si.nr_theirs) if (!si.nr_ours && !si.nr_theirs)
shallow_update = 0; shallow_update = 0;