Skip to content

Commit fa50e7a

Browse files
committed
Merge branch 'jx/remote-archive-over-smart-http'
"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
2 parents e14c0ab + 176cd68 commit fa50e7a

File tree

4 files changed

+68
-22
lines changed

4 files changed

+68
-22
lines changed

http-backend.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct rpc_service {
3838
static struct rpc_service rpc_service[] = {
3939
{ "upload-pack", "uploadpack", 1, 1 },
4040
{ "receive-pack", "receivepack", 0, -1 },
41+
{ "upload-archive", "uploadarchive", 0, -1 },
4142
};
4243

4344
static struct string_list *get_parameters(void)
@@ -639,10 +640,15 @@ static void check_content_type(struct strbuf *hdr, const char *accepted_type)
639640

640641
static void service_rpc(struct strbuf *hdr, char *service_name)
641642
{
642-
const char *argv[] = {NULL, "--stateless-rpc", ".", NULL};
643+
struct strvec argv = STRVEC_INIT;
643644
struct rpc_service *svc = select_service(hdr, service_name);
644645
struct strbuf buf = STRBUF_INIT;
645646

647+
strvec_push(&argv, svc->name);
648+
if (strcmp(service_name, "git-upload-archive"))
649+
strvec_push(&argv, "--stateless-rpc");
650+
strvec_push(&argv, ".");
651+
646652
strbuf_reset(&buf);
647653
strbuf_addf(&buf, "application/x-git-%s-request", svc->name);
648654
check_content_type(hdr, buf.buf);
@@ -655,9 +661,9 @@ static void service_rpc(struct strbuf *hdr, char *service_name)
655661

656662
end_headers(hdr);
657663

658-
argv[0] = svc->name;
659-
run_service(argv, svc->buffer_input);
664+
run_service(argv.v, svc->buffer_input);
660665
strbuf_release(&buf);
666+
strvec_clear(&argv);
661667
}
662668

663669
static int dead;
@@ -723,6 +729,7 @@ static struct service_cmd {
723729
{"GET", "/objects/pack/pack-[0-9a-f]{64}\\.idx$", get_idx_file},
724730

725731
{"POST", "/git-upload-pack$", service_rpc},
732+
{"POST", "/git-upload-archive$", service_rpc},
726733
{"POST", "/git-receive-pack$", service_rpc}
727734
};
728735

remote-curl.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,8 +1446,14 @@ static int stateless_connect(const char *service_name)
14461446
* establish a stateless connection, otherwise we need to tell the
14471447
* client to fallback to using other transport helper functions to
14481448
* complete their request.
1449+
*
1450+
* The "git-upload-archive" service is a read-only operation. Fallback
1451+
* to use "git-upload-pack" service to discover protocol version.
14491452
*/
1450-
discover = discover_refs(service_name, 0);
1453+
if (!strcmp(service_name, "git-upload-archive"))
1454+
discover = discover_refs("git-upload-pack", 0);
1455+
else
1456+
discover = discover_refs(service_name, 0);
14511457
if (discover->version != protocol_v2) {
14521458
printf("fallback\n");
14531459
fflush(stdout);
@@ -1485,9 +1491,11 @@ static int stateless_connect(const char *service_name)
14851491

14861492
/*
14871493
* Dump the capability listing that we got from the server earlier
1488-
* during the info/refs request.
1494+
* during the info/refs request. This does not work with the
1495+
* "git-upload-archive" service.
14891496
*/
1490-
write_or_die(rpc.in, discover->buf, discover->len);
1497+
if (strcmp(service_name, "git-upload-archive"))
1498+
write_or_die(rpc.in, discover->buf, discover->len);
14911499

14921500
/* Until we see EOF keep sending POSTs */
14931501
while (1) {

t/t5003-archive-zip.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,38 @@ check_zip with_untracked2
239239
check_added with_untracked2 untracked one/untracked
240240
check_added with_untracked2 untracked two/untracked
241241

242+
# Test remote archive over HTTP protocol.
243+
#
244+
# Note: this should be the last part of this test suite, because
245+
# by including lib-httpd.sh, the test may end early if httpd tests
246+
# should not be run.
247+
#
248+
. "$TEST_DIRECTORY"/lib-httpd.sh
249+
start_httpd
250+
251+
test_expect_success "setup for HTTP protocol" '
252+
cp -R bare.git "$HTTPD_DOCUMENT_ROOT_PATH/bare.git" &&
253+
git -C "$HTTPD_DOCUMENT_ROOT_PATH/bare.git" \
254+
config http.uploadpack true &&
255+
set_askpass user@host pass@host
256+
'
257+
258+
setup_askpass_helper
259+
260+
test_expect_success 'remote archive does not work with protocol v1' '
261+
test_must_fail git -c protocol.version=1 archive \
262+
--remote="$HTTPD_URL/auth/smart/bare.git" \
263+
--output=remote-http.zip HEAD >actual 2>&1 &&
264+
cat >expect <<-EOF &&
265+
fatal: can${SQ}t connect to subservice git-upload-archive
266+
EOF
267+
test_cmp expect actual
268+
'
269+
270+
test_expect_success 'archive remote http repository' '
271+
git archive --remote="$HTTPD_URL/auth/smart/bare.git" \
272+
--output=remote-http.zip HEAD &&
273+
test_cmp_bin d.zip remote-http.zip
274+
'
275+
242276
test_done

transport-helper.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,8 @@ static int process_connect_service(struct transport *transport,
626626
ret = run_connect(transport, &cmdbuf);
627627
} else if (data->stateless_connect &&
628628
(get_protocol_version_config() == protocol_v2) &&
629-
!strcmp("git-upload-pack", name)) {
629+
(!strcmp("git-upload-pack", name) ||
630+
!strcmp("git-upload-archive", name))) {
630631
strbuf_addf(&cmdbuf, "stateless-connect %s\n", name);
631632
ret = run_connect(transport, &cmdbuf);
632633
if (ret)
@@ -643,14 +644,18 @@ static int process_connect(struct transport *transport,
643644
struct helper_data *data = transport->data;
644645
const char *name;
645646
const char *exec;
647+
int ret;
646648

647649
name = for_push ? "git-receive-pack" : "git-upload-pack";
648650
if (for_push)
649651
exec = data->transport_options.receivepack;
650652
else
651653
exec = data->transport_options.uploadpack;
652654

653-
return process_connect_service(transport, name, exec);
655+
ret = process_connect_service(transport, name, exec);
656+
if (ret)
657+
do_take_over(transport);
658+
return ret;
654659
}
655660

656661
static int connect_helper(struct transport *transport, const char *name,
@@ -660,14 +665,14 @@ static int connect_helper(struct transport *transport, const char *name,
660665

661666
/* Get_helper so connect is inited. */
662667
get_helper(transport);
663-
if (!data->connect)
664-
die(_("operation not supported by protocol"));
665668

666669
if (!process_connect_service(transport, name, exec))
667670
die(_("can't connect to subservice %s"), name);
668671

669672
fd[0] = data->helper->out;
670673
fd[1] = data->helper->in;
674+
675+
do_take_over(transport);
671676
return 0;
672677
}
673678

@@ -682,10 +687,8 @@ static int fetch_refs(struct transport *transport,
682687

683688
get_helper(transport);
684689

685-
if (process_connect(transport, 0)) {
686-
do_take_over(transport);
690+
if (process_connect(transport, 0))
687691
return transport->vtable->fetch_refs(transport, nr_heads, to_fetch);
688-
}
689692

690693
/*
691694
* If we reach here, then the server, the client, and/or the transport
@@ -1142,10 +1145,8 @@ static int push_refs(struct transport *transport,
11421145
{
11431146
struct helper_data *data = transport->data;
11441147

1145-
if (process_connect(transport, 1)) {
1146-
do_take_over(transport);
1148+
if (process_connect(transport, 1))
11471149
return transport->vtable->push_refs(transport, remote_refs, flags);
1148-
}
11491150

11501151
if (!remote_refs) {
11511152
fprintf(stderr,
@@ -1186,11 +1187,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push,
11861187
{
11871188
get_helper(transport);
11881189

1189-
if (process_connect(transport, for_push)) {
1190-
do_take_over(transport);
1190+
if (process_connect(transport, for_push))
11911191
return transport->vtable->get_refs_list(transport, for_push,
11921192
transport_options);
1193-
}
11941193

11951194
return get_refs_list_using_list(transport, for_push);
11961195
}
@@ -1274,10 +1273,8 @@ static int get_bundle_uri(struct transport *transport)
12741273
{
12751274
get_helper(transport);
12761275

1277-
if (process_connect(transport, 0)) {
1278-
do_take_over(transport);
1276+
if (process_connect(transport, 0))
12791277
return transport->vtable->get_bundle_uri(transport);
1280-
}
12811278

12821279
return -1;
12831280
}

0 commit comments

Comments
 (0)