@@ -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,12 @@ 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
+ `<path>.temp` exists, then Git assumes that the `.temp` file is a
+ partial download from a previous attempt and will resume the
+ download from that position.
+
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
@@ -1286,6 +1286,29 @@ static void parse_fetch(struct strbuf *buf)
strbuf_reset(buf);
}
+static void parse_get(const char *arg)
+{
+ struct strbuf url = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ const char *space;
+
+ space = strchr(arg, ' ');
+
+ if (!space)
+ die(_("protocol error: expected '<url> <path>', missing space"));
+
+ strbuf_add(&url, arg, space - arg);
+ strbuf_addstr(&path, space + 1);
+
+ if (http_get_file(url.buf, path.buf, NULL))
+ die(_("failed to download file at URL '%s'"), url.buf);
+
+ strbuf_release(&url);
+ strbuf_release(&path);
+ printf("\n");
+ fflush(stdout);
+}
+
static int push_dav(int nr_spec, const char **specs)
{
struct child_process child = CHILD_PROCESS_INIT;
@@ -1564,9 +1587,14 @@ int cmd_main(int argc, const char **argv)
printf("unsupported\n");
fflush(stdout);
+ } else if (skip_prefix(buf.buf, "get ", &arg)) {
+ parse_get(arg);
+ 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");
new file mode 100755
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='test downloading a file by URL'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'get by URL: 404' '
+ test_when_finished "rm -f file.temp" &&
+ url="$HTTPD_URL/none.txt" &&
+ cat >input <<-EOF &&
+ capabilities
+ get $url file1
+ EOF
+
+ test_must_fail git remote-http $url <input 2>err &&
+ test_path_is_missing file1 &&
+ grep "failed to download file at URL" err
+'
+
+test_expect_success 'get by URL: 200' '
+ echo data >"$HTTPD_DOCUMENT_ROOT_PATH/exists.txt" &&
+
+ url="$HTTPD_URL/exists.txt" &&
+ cat >input <<-EOF &&
+ capabilities
+ get $url file2
+
+ EOF
+
+ git remote-http $url <input &&
+ test_cmp "$HTTPD_DOCUMENT_ROOT_PATH/exists.txt" file2
+'
+
+test_done