push: accept push options

This implements everything that is required on the client side to make use of push options from the porcelain push command. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Stefan Beller committed Jul 14, 2016 at 14:49 UTC f6a4e61fbb647928d615a0befaec163a5d2bf4af
6 files changed +63 -4
Documentation/git-push.txt
+7 -1
@@ -11,7 +11,7 @@ SYNOPSIS
11 [verse]
12 'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
13 [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
14 - [-u | --set-upstream]
14 + [-u | --set-upstream] [--push-option=<string>]
15 [--[no-]signed|--sign=(true|false|if-asked)]
16 [--force-with-lease[=<refname>[:<expect>]]]
17 [--no-verify] [<repository> [<refspec>...]]
@@ -156,6 +156,12 @@ already exists on the remote side.
156 Either all refs are updated, or on error, no refs are updated.
157 If the server does not support atomic pushes the push will fail.
158
159 +-o::
160 +--push-option::
161 + Transmit the given string to the server, which passes them to
162 + the pre-receive as well as the post-receive hook. The given string
163 + must not contain a NUL or LF character.
164 +
165 --receive-pack=<git-receive-pack>::
166 --exec=<git-receive-pack>::
167 Path to the 'git-receive-pack' program on the remote
builtin/push.c
+18 -3
@@ -353,7 +353,8 @@ static int push_with_options(struct transport *transport, int flags)
353 return 1;
354 }
355
356 -static int do_push(const char *repo, int flags)
356 +static int do_push(const char *repo, int flags,
357 + const struct string_list *push_options)
358 {
359 int i, errs;
360 struct remote *remote = pushremote_get(repo);
@@ -376,6 +377,9 @@ static int do_push(const char *repo, int flags)
377 if (remote->mirror)
378 flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
379
380 + if (push_options->nr)
381 + flags |= TRANSPORT_PUSH_OPTIONS;
382 +
383 if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
384 if (!strcmp(*refspec, "refs/tags/*"))
385 return error(_("--all and --tags are incompatible"));
@@ -406,13 +410,16 @@ static int do_push(const char *repo, int flags)
410 for (i = 0; i < url_nr; i++) {
411 struct transport *transport =
412 transport_get(remote, url[i]);
413 + if (flags & TRANSPORT_PUSH_OPTIONS)
414 + transport->push_options = push_options;
415 if (push_with_options(transport, flags))
416 errs++;
417 }
418 } else {
419 struct transport *transport =
420 transport_get(remote, NULL);
415 -
421 + if (flags & TRANSPORT_PUSH_OPTIONS)
422 + transport->push_options = push_options;
423 if (push_with_options(transport, flags))
424 errs++;
425 }
@@ -500,6 +507,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
507 int push_cert = -1;
508 int rc;
509 const char *repo = NULL; /* default repository */
510 + static struct string_list push_options = STRING_LIST_INIT_DUP;
511 + static struct string_list_item *item;
512 +
513 struct option options[] = {
514 OPT__VERBOSITY(&verbosity),
515 OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
@@ -533,6 +543,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
543 0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
544 PARSE_OPT_OPTARG, option_parse_push_signed },
545 OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
546 + OPT_STRING_LIST('o', "push-option", &push_options, N_("server-specific"), N_("option to transmit")),
547 OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
548 TRANSPORT_FAMILY_IPV4),
549 OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
@@ -563,7 +574,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
574 set_refspecs(argv + 1, argc - 1, repo);
575 }
576
566 - rc = do_push(repo, flags);
577 + for_each_string_list_item(item, &push_options)
578 + if (strchr(item->string, '\n'))
579 + die(_("push options must not have new line characters"));
580 +
581 + rc = do_push(repo, flags, &push_options);
582 if (rc == -1)
583 usage_with_options(push_usage, options);
584 else
send-pack.c
+27
@@ -260,6 +260,7 @@ static int generate_push_cert(struct strbuf *req_buf,
260 const char *push_cert_nonce)
261 {
262 const struct ref *ref;
263 + struct string_list_item *item;
264 char *signing_key = xstrdup(get_signing_key());
265 const char *cp, *np;
266 struct strbuf cert = STRBUF_INIT;
@@ -276,6 +277,9 @@ static int generate_push_cert(struct strbuf *req_buf,
277 }
278 if (push_cert_nonce[0])
279 strbuf_addf(&cert, "nonce %s\n", push_cert_nonce);
280 + if (args->push_options)
281 + for_each_string_list_item(item, args->push_options)
282 + strbuf_addf(&cert, "push-option %s\n", item->string);
283 strbuf_addstr(&cert, "\n");
284
285 for (ref = remote_refs; ref; ref = ref->next) {
@@ -370,6 +374,8 @@ int send_pack(struct send_pack_args *args,
374 int agent_supported = 0;
375 int use_atomic = 0;
376 int atomic_supported = 0;
377 + int use_push_options = 0;
378 + int push_options_supported = 0;
379 unsigned cmds_sent = 0;
380 int ret;
381 struct async demux;
@@ -392,6 +398,8 @@ int send_pack(struct send_pack_args *args,
398 args->use_thin_pack = 0;
399 if (server_supports("atomic"))
400 atomic_supported = 1;
401 + if (server_supports("push-options"))
402 + push_options_supported = 1;
403
404 if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
405 int len;
@@ -418,6 +426,11 @@ int send_pack(struct send_pack_args *args,
426
427 use_atomic = atomic_supported && args->atomic;
428
429 + if (args->push_options && !push_options_supported)
430 + die(_("the receiving end does not support push options"));
431 +
432 + use_push_options = push_options_supported && args->push_options;
433 +
434 if (status_report)
435 strbuf_addstr(&cap_buf, " report-status");
436 if (use_sideband)
@@ -426,6 +439,8 @@ int send_pack(struct send_pack_args *args,
439 strbuf_addstr(&cap_buf, " quiet");
440 if (use_atomic)
441 strbuf_addstr(&cap_buf, " atomic");
442 + if (use_push_options)
443 + strbuf_addstr(&cap_buf, " push-options");
444 if (agent_supported)
445 strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized());
446
@@ -512,6 +527,18 @@ int send_pack(struct send_pack_args *args,
527 strbuf_release(&req_buf);
528 strbuf_release(&cap_buf);
529
530 + if (use_push_options) {
531 + struct string_list_item *item;
532 + struct strbuf sb = STRBUF_INIT;
533 +
534 + for_each_string_list_item(item, args->push_options)
535 + packet_buf_write(&sb, "%s", item->string);
536 +
537 + write_or_die(out, sb.buf, sb.len);
538 + packet_flush(out);
539 + strbuf_release(&sb);
540 + }
541 +
542 if (use_sideband && cmds_sent) {
543 memset(&demux, 0, sizeof(demux));
544 demux.proc = sideband_demux;
send-pack.h
+3
@@ -1,6 +1,8 @@
1 #ifndef SEND_PACK_H
2 #define SEND_PACK_H
3
4 +#include "string-list.h"
5 +
6 /* Possible values for push_cert field in send_pack_args. */
7 #define SEND_PACK_PUSH_CERT_NEVER 0
8 #define SEND_PACK_PUSH_CERT_IF_ASKED 1
@@ -21,6 +23,7 @@ struct send_pack_args {
23 push_cert:2,
24 stateless_rpc:1,
25 atomic:1;
26 + const struct string_list *push_options;
27 };
28
29 struct option;
transport.c
+1
@@ -510,6 +510,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
510 args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
511 args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);
512 args.atomic = !!(flags & TRANSPORT_PUSH_ATOMIC);
513 + args.push_options = transport->push_options;
514 args.url = transport->url;
515
516 if (flags & TRANSPORT_PUSH_CERT_ALWAYS)
transport.h
+7
@@ -48,6 +48,12 @@ struct transport {
48 */
49 unsigned cloning : 1;
50
51 + /*
52 + * These strings will be passed to the {pre, post}-receive hook,
53 + * on the remote side, if both sides support the push options capability.
54 + */
55 + const struct string_list *push_options;
56 +
57 /**
58 * Returns 0 if successful, positive if the option is not
59 * recognized or is inapplicable, and negative if the option
@@ -134,6 +140,7 @@ struct transport {
140 #define TRANSPORT_PUSH_CERT_ALWAYS 2048
141 #define TRANSPORT_PUSH_CERT_IF_ASKED 4096
142 #define TRANSPORT_PUSH_ATOMIC 8192
143 +#define TRANSPORT_PUSH_OPTIONS 16384
144
145 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
146 #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)