From: Derrick Stolee <derrickstolee@xxxxxxxxxx> A future change will want a way to download a file over HTTP(S) using the simplest of download mechanisms. We do not want to assume that the server on the other side understands anything about the Git protocol but could be a simple static web server. Create the new 'get' capability for the remote helpers which advertises that the 'get' command is avalable. A caller can send a line containing 'get <url> <path>' to download the file at <url> into the file at <path>. RFC-TODO: This change requires tests directly on the remote helper. Signed-off-by: Derrick Stolee <derrickstolee@xxxxxxxxxx> --- Documentation/gitremote-helpers.txt | 6 ++++++ remote-curl.c | 32 +++++++++++++++++++++++++++++ t/t6021-fetch-bundle.sh | 23 +++++++++++++++++++++ transport-helper.c | 5 ++++- 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100755 t/t6021-fetch-bundle.sh diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index 6f1e269ae43..f82588601a9 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -168,6 +168,9 @@ Supported commands: 'list', 'import'. Can guarantee that when a clone is requested, the received pack is self contained and is connected. +'get':: + Can use the 'get' command to download a file from a given URI. + If a helper advertises 'connect', Git will use it if possible and fall back to another capability if the helper requests so when connecting (see the 'connect' command under COMMANDS). @@ -418,6 +421,9 @@ Supported if the helper has the "connect" capability. + Supported if the helper has the "stateless-connect" capability. +'get' <uri> <path>:: + Downloads the file from the given `<uri>` to the given `<path>`. + If a fatal error occurs, the program writes the error message to stderr and exits. The caller should expect that a suitable error message has been printed if the child closes the connection without diff --git a/remote-curl.c b/remote-curl.c index 67f178b1120..53750d88e76 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -1276,6 +1276,33 @@ static void parse_fetch(struct strbuf *buf) strbuf_reset(buf); } +static void parse_get(struct strbuf *buf) +{ + struct http_get_options opts = { 0 }; + struct strbuf url = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + const char *p, *space; + + if (!skip_prefix(buf->buf, "get ", &p)) + die(_("http transport does not support %s"), buf->buf); + + space = strchr(p, ' '); + + if (!space) + die(_("protocol error: expected '<url> <path>', missing space")); + + strbuf_add(&url, p, space - p); + strbuf_addstr(&path, space + 1); + + http_get_file(url.buf, path.buf, &opts); + + strbuf_release(&url); + strbuf_release(&path); + printf("\n"); + fflush(stdout); + strbuf_reset(buf); +} + static int push_dav(int nr_spec, const char **specs) { struct child_process child = CHILD_PROCESS_INIT; @@ -1549,9 +1576,14 @@ int cmd_main(int argc, const char **argv) printf("unsupported\n"); fflush(stdout); + } else if (skip_prefix(buf.buf, "get ", &arg)) { + parse_get(&buf); + fflush(stdout); + } else if (!strcmp(buf.buf, "capabilities")) { printf("stateless-connect\n"); printf("fetch\n"); + printf("get\n"); printf("option\n"); printf("push\n"); printf("check-connectivity\n"); diff --git a/t/t6021-fetch-bundle.sh b/t/t6021-fetch-bundle.sh new file mode 100755 index 00000000000..8ae16009ba0 --- /dev/null +++ b/t/t6021-fetch-bundle.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description='test fetching files and bundles over HTTP' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'set up source repo' ' + git init src && + test_commit -C src one +' + +test_expect_success 'fail to get a file over HTTP' ' + cat >input <<-EOF && + get $HTTPD_URL/does-not-exist.txt download-failed.txt + + EOF + git remote-https "$HTTPD_URL" <input 2>err && + test_path_is_missing download-failed.txt +' + +test_done diff --git a/transport-helper.c b/transport-helper.c index b4dbbabb0c2..dfbeaebe40c 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -33,7 +33,8 @@ struct helper_data { check_connectivity : 1, no_disconnect_req : 1, no_private_update : 1, - object_format : 1; + object_format : 1, + get : 1; /* * As an optimization, the transport code may invoke fetch before @@ -210,6 +211,8 @@ static struct child_process *get_helper(struct transport *transport) data->no_private_update = 1; } else if (starts_with(capname, "object-format")) { data->object_format = 1; + } else if (!strcmp(capname, "get")) { + data->get = 1; } else if (mandatory) { die(_("unknown mandatory capability %s; this remote " "helper probably needs newer version of Git"), -- gitgitgadget