]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jx/remote-archive-over-smart-http'
authorJunio C Hamano <gitster@pobox.com>
Tue, 30 Jan 2024 21:34:12 +0000 (13:34 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 30 Jan 2024 21:34:12 +0000 (13:34 -0800)
"git archive --remote=<remote>" learned to talk over the smart
http (aka stateless) transport.

* jx/remote-archive-over-smart-http:
  transport-helper: call do_take_over() in process_connect
  transport-helper: call do_take_over() in connect_helper
  http-backend: new rpc-service for git-upload-archive
  transport-helper: protocol v2 supports upload-archive
  remote-curl: supports git-upload-archive service
  transport-helper: no connection restriction in connect_helper

http-backend.c
remote-curl.c
t/t5003-archive-zip.sh
transport-helper.c

index ff07b87e6461446610c35708a39f22a5e5b36aff..1ed1e29d0706bfe51e2074cabe393e0ed6eba7c7 100644 (file)
@@ -38,6 +38,7 @@ struct rpc_service {
 static struct rpc_service rpc_service[] = {
        { "upload-pack", "uploadpack", 1, 1 },
        { "receive-pack", "receivepack", 0, -1 },
+       { "upload-archive", "uploadarchive", 0, -1 },
 };
 
 static struct string_list *get_parameters(void)
@@ -639,10 +640,15 @@ static void check_content_type(struct strbuf *hdr, const char *accepted_type)
 
 static void service_rpc(struct strbuf *hdr, char *service_name)
 {
-       const char *argv[] = {NULL, "--stateless-rpc", ".", NULL};
+       struct strvec argv = STRVEC_INIT;
        struct rpc_service *svc = select_service(hdr, service_name);
        struct strbuf buf = STRBUF_INIT;
 
+       strvec_push(&argv, svc->name);
+       if (strcmp(service_name, "git-upload-archive"))
+               strvec_push(&argv, "--stateless-rpc");
+       strvec_push(&argv, ".");
+
        strbuf_reset(&buf);
        strbuf_addf(&buf, "application/x-git-%s-request", svc->name);
        check_content_type(hdr, buf.buf);
@@ -655,9 +661,9 @@ static void service_rpc(struct strbuf *hdr, char *service_name)
 
        end_headers(hdr);
 
-       argv[0] = svc->name;
-       run_service(argv, svc->buffer_input);
+       run_service(argv.v, svc->buffer_input);
        strbuf_release(&buf);
+       strvec_clear(&argv);
 }
 
 static int dead;
@@ -723,6 +729,7 @@ static struct service_cmd {
        {"GET", "/objects/pack/pack-[0-9a-f]{64}\\.idx$", get_idx_file},
 
        {"POST", "/git-upload-pack$", service_rpc},
+       {"POST", "/git-upload-archive$", service_rpc},
        {"POST", "/git-receive-pack$", service_rpc}
 };
 
index cb0182b582a5cb4d13718d4a47cfb07c078464a0..1161dc7fed689259141ae2eb5403d84b906027d3 100644 (file)
@@ -1446,8 +1446,14 @@ static int stateless_connect(const char *service_name)
         * establish a stateless connection, otherwise we need to tell the
         * client to fallback to using other transport helper functions to
         * complete their request.
+        *
+        * The "git-upload-archive" service is a read-only operation. Fallback
+        * to use "git-upload-pack" service to discover protocol version.
         */
-       discover = discover_refs(service_name, 0);
+       if (!strcmp(service_name, "git-upload-archive"))
+               discover = discover_refs("git-upload-pack", 0);
+       else
+               discover = discover_refs(service_name, 0);
        if (discover->version != protocol_v2) {
                printf("fallback\n");
                fflush(stdout);
@@ -1485,9 +1491,11 @@ static int stateless_connect(const char *service_name)
 
        /*
         * Dump the capability listing that we got from the server earlier
-        * during the info/refs request.
+        * during the info/refs request. This does not work with the
+        * "git-upload-archive" service.
         */
-       write_or_die(rpc.in, discover->buf, discover->len);
+       if (strcmp(service_name, "git-upload-archive"))
+               write_or_die(rpc.in, discover->buf, discover->len);
 
        /* Until we see EOF keep sending POSTs */
        while (1) {
index fc499cdff01d01a6079221e78b50a7924e5ecb71..961c6aac2561354f6ad57270c1362fe73c850924 100755 (executable)
@@ -239,4 +239,38 @@ check_zip with_untracked2
 check_added with_untracked2 untracked one/untracked
 check_added with_untracked2 untracked two/untracked
 
+# Test remote archive over HTTP protocol.
+#
+# Note: this should be the last part of this test suite, because
+# by including lib-httpd.sh, the test may end early if httpd tests
+# should not be run.
+#
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success "setup for HTTP protocol" '
+       cp -R bare.git "$HTTPD_DOCUMENT_ROOT_PATH/bare.git" &&
+       git -C "$HTTPD_DOCUMENT_ROOT_PATH/bare.git" \
+               config http.uploadpack true &&
+       set_askpass user@host pass@host
+'
+
+setup_askpass_helper
+
+test_expect_success 'remote archive does not work with protocol v1' '
+       test_must_fail git -c protocol.version=1 archive \
+               --remote="$HTTPD_URL/auth/smart/bare.git" \
+               --output=remote-http.zip HEAD >actual 2>&1 &&
+       cat >expect <<-EOF &&
+       fatal: can${SQ}t connect to subservice git-upload-archive
+       EOF
+       test_cmp expect actual
+'
+
+test_expect_success 'archive remote http repository' '
+       git archive --remote="$HTTPD_URL/auth/smart/bare.git" \
+               --output=remote-http.zip HEAD &&
+       test_cmp_bin d.zip remote-http.zip
+'
+
 test_done
index e34a8f47cfbf5cba150e1aa7c6267fc2b1c080c0..67644638734887e5eec4363bc13484c8c60b2630 100644 (file)
@@ -626,7 +626,8 @@ static int process_connect_service(struct transport *transport,
                ret = run_connect(transport, &cmdbuf);
        } else if (data->stateless_connect &&
                   (get_protocol_version_config() == protocol_v2) &&
-                  !strcmp("git-upload-pack", name)) {
+                  (!strcmp("git-upload-pack", name) ||
+                   !strcmp("git-upload-archive", name))) {
                strbuf_addf(&cmdbuf, "stateless-connect %s\n", name);
                ret = run_connect(transport, &cmdbuf);
                if (ret)
@@ -643,6 +644,7 @@ static int process_connect(struct transport *transport,
        struct helper_data *data = transport->data;
        const char *name;
        const char *exec;
+       int ret;
 
        name = for_push ? "git-receive-pack" : "git-upload-pack";
        if (for_push)
@@ -650,7 +652,10 @@ static int process_connect(struct transport *transport,
        else
                exec = data->transport_options.uploadpack;
 
-       return process_connect_service(transport, name, exec);
+       ret = process_connect_service(transport, name, exec);
+       if (ret)
+               do_take_over(transport);
+       return ret;
 }
 
 static int connect_helper(struct transport *transport, const char *name,
@@ -660,14 +665,14 @@ static int connect_helper(struct transport *transport, const char *name,
 
        /* Get_helper so connect is inited. */
        get_helper(transport);
-       if (!data->connect)
-               die(_("operation not supported by protocol"));
 
        if (!process_connect_service(transport, name, exec))
                die(_("can't connect to subservice %s"), name);
 
        fd[0] = data->helper->out;
        fd[1] = data->helper->in;
+
+       do_take_over(transport);
        return 0;
 }
 
@@ -682,10 +687,8 @@ static int fetch_refs(struct transport *transport,
 
        get_helper(transport);
 
-       if (process_connect(transport, 0)) {
-               do_take_over(transport);
+       if (process_connect(transport, 0))
                return transport->vtable->fetch_refs(transport, nr_heads, to_fetch);
-       }
 
        /*
         * If we reach here, then the server, the client, and/or the transport
@@ -1142,10 +1145,8 @@ static int push_refs(struct transport *transport,
 {
        struct helper_data *data = transport->data;
 
-       if (process_connect(transport, 1)) {
-               do_take_over(transport);
+       if (process_connect(transport, 1))
                return transport->vtable->push_refs(transport, remote_refs, flags);
-       }
 
        if (!remote_refs) {
                fprintf(stderr,
@@ -1186,11 +1187,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push,
 {
        get_helper(transport);
 
-       if (process_connect(transport, for_push)) {
-               do_take_over(transport);
+       if (process_connect(transport, for_push))
                return transport->vtable->get_refs_list(transport, for_push,
                                                        transport_options);
-       }
 
        return get_refs_list_using_list(transport, for_push);
 }
@@ -1274,10 +1273,8 @@ static int get_bundle_uri(struct transport *transport)
 {
        get_helper(transport);
 
-       if (process_connect(transport, 0)) {
-               do_take_over(transport);
+       if (process_connect(transport, 0))
                return transport->vtable->get_bundle_uri(transport);
-       }
 
        return -1;
 }