]> git.ipfire.org Git - thirdparty/git.git/commitdiff
bundle-uri: add support for http(s):// and file://
authorDerrick Stolee <derrickstolee@github.com>
Tue, 9 Aug 2022 13:11:42 +0000 (13:11 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Aug 2022 21:07:37 +0000 (14:07 -0700)
The previous change created the 'git clone --bundle-uri=<uri>' option.
Currently, <uri> must be a filename.

Update copy_uri_to_file() to first inspect the URI for an HTTP(S) prefix
and use git-remote-https as the way to download the data at that URI.
Otherwise, check to see if file:// is present and modify the prefix
accordingly.

Reviewed-by: Josh Steadmon <steadmon@google.com>
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
bundle-uri.c
t/t5558-clone-bundle-uri.sh

index b35babc36aa04ddab452f485e1d353c3fc7e77c8..4a8cc74ed0531eaf3fcfb0023d198cea4aa2188d 100644 (file)
@@ -23,10 +23,74 @@ static int find_temp_filename(struct strbuf *name)
        return 0;
 }
 
-static int copy_uri_to_file(const char *file, const char *uri)
+static int download_https_uri_to_file(const char *file, const char *uri)
 {
-       /* File-based URIs only for now. */
-       return copy_file(file, uri, 0);
+       int result = 0;
+       struct child_process cp = CHILD_PROCESS_INIT;
+       FILE *child_in = NULL, *child_out = NULL;
+       struct strbuf line = STRBUF_INIT;
+       int found_get = 0;
+
+       strvec_pushl(&cp.args, "git-remote-https", uri, NULL);
+       cp.in = -1;
+       cp.out = -1;
+
+       if (start_command(&cp))
+               return 1;
+
+       child_in = fdopen(cp.in, "w");
+       if (!child_in) {
+               result = 1;
+               goto cleanup;
+       }
+
+       child_out = fdopen(cp.out, "r");
+       if (!child_out) {
+               result = 1;
+               goto cleanup;
+       }
+
+       fprintf(child_in, "capabilities\n");
+       fflush(child_in);
+
+       while (!strbuf_getline(&line, child_out)) {
+               if (!line.len)
+                       break;
+               if (!strcmp(line.buf, "get"))
+                       found_get = 1;
+       }
+       strbuf_release(&line);
+
+       if (!found_get) {
+               result = error(_("insufficient capabilities"));
+               goto cleanup;
+       }
+
+       fprintf(child_in, "get %s %s\n\n", uri, file);
+
+cleanup:
+       if (child_in)
+               fclose(child_in);
+       if (finish_command(&cp))
+               return 1;
+       if (child_out)
+               fclose(child_out);
+       return result;
+}
+
+static int copy_uri_to_file(const char *filename, const char *uri)
+{
+       const char *out;
+
+       if (starts_with(uri, "https:") ||
+           starts_with(uri, "http:"))
+               return download_https_uri_to_file(filename, uri);
+
+       if (skip_prefix(uri, "file://", &out))
+               uri = out;
+
+       /* Copy as a file */
+       return copy_file(filename, uri, 0);
 }
 
 static int unbundle_from_file(struct repository *r, const char *file)
index f709bcb729caf45e2514c12eb79ca243ee4640c2..ad666a2d28a553fced4ba0aa55af43c60671222c 100755 (executable)
@@ -33,4 +33,49 @@ test_expect_success 'clone with path bundle' '
        test_cmp expect actual
 '
 
+test_expect_success 'clone with file:// bundle' '
+       git clone --bundle-uri="file://$(pwd)/clone-from/B.bundle" \
+               clone-from clone-file &&
+       git -C clone-file rev-parse refs/bundles/topic >actual &&
+       git -C clone-from rev-parse topic >expect &&
+       test_cmp expect actual
+'
+
+#########################################################################
+# HTTP tests begin here
+
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+test_expect_success 'fail to fetch from non-existent HTTP URL' '
+       test_when_finished rm -rf test &&
+       git clone --bundle-uri="$HTTPD_URL/does-not-exist" . test 2>err &&
+       grep "failed to download bundle from URI" err
+'
+
+test_expect_success 'fail to fetch from non-bundle HTTP URL' '
+       test_when_finished rm -rf test &&
+       echo bogus >"$HTTPD_DOCUMENT_ROOT_PATH/bogus" &&
+       git clone --bundle-uri="$HTTPD_URL/bogus" . test 2>err &&
+       grep "is not a bundle" err
+'
+
+test_expect_success 'clone HTTP bundle' '
+       cp clone-from/B.bundle "$HTTPD_DOCUMENT_ROOT_PATH/B.bundle" &&
+
+       git clone --no-local --mirror clone-from \
+               "$HTTPD_DOCUMENT_ROOT_PATH/fetch.git" &&
+
+       git clone --bundle-uri="$HTTPD_URL/B.bundle" \
+               "$HTTPD_URL/smart/fetch.git" clone-http &&
+       git -C clone-http rev-parse refs/bundles/topic >actual &&
+       git -C clone-from rev-parse topic >expect &&
+       test_cmp expect actual &&
+
+       test_config -C clone-http log.excludedecoration refs/bundle/
+'
+
+# Do not add tests here unless they use the HTTP server, as they will
+# not run unless the HTTP dependencies exist.
+
 test_done