Teach remote-curl to understand push options and to be able to convey
them across HTTP.

Signed-off-by: Brandon Williams <bmw...@google.com>
---
 builtin/send-pack.c     |  5 +++++
 remote-curl.c           |  8 ++++++++
 t/t5545-push-options.sh | 30 +++++++++++++++++++++++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 1ff5a6753..6796f3368 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -152,6 +152,7 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
        int progress = -1;
        int from_stdin = 0;
        struct push_cas_option cas = {0};
+       struct string_list push_options = STRING_LIST_INIT_DUP;
 
        struct option options[] = {
                OPT__VERBOSITY(&verbose),
@@ -171,6 +172,9 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
                OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless 
RPC protocol")),
                OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
                OPT_BOOL(0, "helper-status", &helper_status, N_("print status 
from remote helper")),
+               OPT_STRING_LIST('o', "push-option", &push_options,
+                               N_("server-specific"),
+                               N_("option to transmit")),
                { OPTION_CALLBACK,
                  0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
                  N_("require old value of ref to be at this value"),
@@ -199,6 +203,7 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
        args.use_thin_pack = use_thin_pack;
        args.atomic = atomic;
        args.stateless_rpc = stateless_rpc;
+       args.push_options = push_options.nr ? &push_options : NULL;
 
        if (from_stdin) {
                struct argv_array all_refspecs = ARGV_ARRAY_INIT;
diff --git a/remote-curl.c b/remote-curl.c
index 34a97e732..e953d06f6 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -22,6 +22,7 @@ struct options {
        unsigned long depth;
        char *deepen_since;
        struct string_list deepen_not;
+       struct string_list push_options;
        unsigned progress : 1,
                check_self_contained_and_connected : 1,
                cloning : 1,
@@ -139,6 +140,9 @@ static int set_option(const char *name, const char *value)
                else
                        return -1;
                return 0;
+       } else if (!strcmp(name, "push-option")) {
+               string_list_append(&options.push_options, value);
+               return 0;
 
 #if LIBCURL_VERSION_NUM >= 0x070a08
        } else if (!strcmp(name, "family")) {
@@ -943,6 +947,9 @@ static int push_git(struct discovery *heads, int nr_spec, 
char **specs)
                argv_array_push(&args, "--quiet");
        else if (options.verbosity > 1)
                argv_array_push(&args, "--verbose");
+       for (i = 0; i < options.push_options.nr; i++)
+               argv_array_pushf(&args, "--push-option=%s",
+                                options.push_options.items[i].string);
        argv_array_push(&args, options.progress ? "--progress" : 
"--no-progress");
        for_each_string_list_item(cas_option, &cas_options)
                argv_array_push(&args, cas_option->string);
@@ -1028,6 +1035,7 @@ int cmd_main(int argc, const char **argv)
        options.progress = !!isatty(2);
        options.thin = 1;
        string_list_init(&options.deepen_not, 1);
+       string_list_init(&options.push_options, 1);
 
        remote = remote_get(argv[1]);
 
diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh
index 9a57a7d8f..ac62083e9 100755
--- a/t/t5545-push-options.sh
+++ b/t/t5545-push-options.sh
@@ -102,7 +102,9 @@ test_expect_success 'two push options work' '
        test_cmp expect upstream/.git/hooks/post-receive.push_options
 '
 
-test_expect_success 'push option denied properly by http remote helper' '\
+test_expect_success 'push option denied properly by http server' '
+       test_when_finished "rm -rf test_http_clone" &&
+       test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH\"/upstream.git" 
&&
        mk_repo_pair &&
        git -C upstream config receive.advertisePushOptions false &&
        git -C upstream config http.receivepack true &&
@@ -113,6 +115,32 @@ test_expect_success 'push option denied properly by http 
remote helper' '\
        git -C test_http_clone push origin master
 '
 
+test_expect_success 'push options work properly across http' '
+       test_when_finished "rm -rf test_http_clone" &&
+       test_when_finished "rm -rf \"$HTTPD_DOCUMENT_ROOT_PATH\"/upstream.git" 
&&
+       mk_repo_pair &&
+       git -C upstream config receive.advertisePushOptions true &&
+       git -C upstream config http.receivepack true &&
+       cp -R upstream/.git "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git &&
+       git clone "$HTTPD_URL"/smart/upstream test_http_clone &&
+
+       test_commit -C test_http_clone one &&
+       git -C test_http_clone push origin master &&
+       git -C "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git rev-parse --verify 
master >expect &&
+       git -C test_http_clone rev-parse --verify master >actual &&
+       test_cmp expect actual &&
+
+       test_commit -C test_http_clone two &&
+       git -C test_http_clone push --push-option=asdf --push-option="more 
structured text" origin master &&
+       printf "asdf\nmore structured text\n" >expect &&
+       test_cmp expect 
"$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/pre-receive.push_options &&
+       test_cmp expect 
"$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/post-receive.push_options &&
+
+       git -C "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git rev-parse --verify 
master >expect &&
+       git -C test_http_clone rev-parse --verify master >actual &&
+       test_cmp expect actual
+'
+
 stop_httpd
 
 test_done
-- 
2.12.1.500.gab5fba24ee-goog

Reply via email to