aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerrick Stolee <derrickstolee@github.com>2022-08-09 13:11:39 +0000
committerJunio C Hamano <gitster@pobox.com>2022-08-10 14:07:37 -0700
commitb5624a44744d6e5f9c749e4df02932c724e2097e (patch)
tree550bb596d7bb2c39621d2d99aa7d7007b98a203b
parentThe sixth batch (diff)
downloadgit-b5624a44744d6e5f9c749e4df02932c724e2097e.tar.gz
git-b5624a44744d6e5f9c749e4df02932c724e2097e.zip
remote-curl: add 'get' capability
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>. Reviewed-by: Josh Steadmon <steadmon@google.com> Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/gitremote-helpers.txt9
-rw-r--r--remote-curl.c28
-rwxr-xr-xt/t5557-http-get.sh37
3 files changed, 74 insertions, 0 deletions
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index 6f1e269ae4..ed8da428c9 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,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
diff --git a/remote-curl.c b/remote-curl.c
index b8758757ec..72dfb8fb86 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -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");
diff --git a/t/t5557-http-get.sh b/t/t5557-http-get.sh
new file mode 100755
index 0000000000..09fb0bd9a8
--- /dev/null
+++ b/t/t5557-http-get.sh
@@ -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