bundle-uri: add support for http(s):// and file://
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>
Derrick Stolee committed
Aug 9, 2022 at 13:11 UTC
59c1752ab6768cb9c380f0a7c9d06af79d183f67
2 files changed
+112
-3
bundle-uri.c
+67
-3
@@ -23,10 +23,74 @@ static int find_temp_filename(struct strbuf *name)
23
return 0;
24
}
25
26
-static int copy_uri_to_file(const char *file, const char *uri)
26
+static int download_https_uri_to_file(const char *file, const char *uri)
27
{
28
- /* File-based URIs only for now. */
29
- return copy_file(file, uri, 0);
28
+ int result = 0;
29
+ struct child_process cp = CHILD_PROCESS_INIT;
30
+ FILE *child_in = NULL, *child_out = NULL;
31
+ struct strbuf line = STRBUF_INIT;
32
+ int found_get = 0;
33
+
34
+ strvec_pushl(&cp.args, "git-remote-https", uri, NULL);
35
+ cp.in = -1;
36
+ cp.out = -1;
37
+
38
+ if (start_command(&cp))
39
+ return 1;
40
+
41
+ child_in = fdopen(cp.in, "w");
42
+ if (!child_in) {
43
+ result = 1;
44
+ goto cleanup;
45
+ }
46
+
47
+ child_out = fdopen(cp.out, "r");
48
+ if (!child_out) {
49
+ result = 1;
50
+ goto cleanup;
51
+ }
52
+
53
+ fprintf(child_in, "capabilities\n");
54
+ fflush(child_in);
55
+
56
+ while (!strbuf_getline(&line, child_out)) {
57
+ if (!line.len)
58
+ break;
59
+ if (!strcmp(line.buf, "get"))
60
+ found_get = 1;
61
+ }
62
+ strbuf_release(&line);
63
+
64
+ if (!found_get) {
65
+ result = error(_("insufficient capabilities"));
66
+ goto cleanup;
67
+ }
68
+
69
+ fprintf(child_in, "get %s %s\n\n", uri, file);
70
+
71
+cleanup:
72
+ if (child_in)
73
+ fclose(child_in);
74
+ if (finish_command(&cp))
75
+ return 1;
76
+ if (child_out)
77
+ fclose(child_out);
78
+ return result;
79
+}
80
+
81
+static int copy_uri_to_file(const char *filename, const char *uri)
82
+{
83
+ const char *out;
84
+
85
+ if (starts_with(uri, "https:") ||
86
+ starts_with(uri, "http:"))
87
+ return download_https_uri_to_file(filename, uri);
88
+
89
+ if (skip_prefix(uri, "file://", &out))
90
+ uri = out;
91
+
92
+ /* Copy as a file */
93
+ return copy_file(filename, uri, 0);
94
}
95
96
static int unbundle_from_file(struct repository *r, const char *file)
t/t5558-clone-bundle-uri.sh
+45
@@ -33,4 +33,49 @@ test_expect_success 'clone with path bundle' '
33
test_cmp expect actual
34
'
35
36
+test_expect_success 'clone with file:// bundle' '
37
+ git clone --bundle-uri="file://$(pwd)/clone-from/B.bundle" \
38
+ clone-from clone-file &&
39
+ git -C clone-file rev-parse refs/bundles/topic >actual &&
40
+ git -C clone-from rev-parse topic >expect &&
41
+ test_cmp expect actual
42
+'
43
+
44
+#########################################################################
45
+# HTTP tests begin here
46
+
47
+. "$TEST_DIRECTORY"/lib-httpd.sh
48
+start_httpd
49
+
50
+test_expect_success 'fail to fetch from non-existent HTTP URL' '
51
+ test_when_finished rm -rf test &&
52
+ git clone --bundle-uri="$HTTPD_URL/does-not-exist" . test 2>err &&
53
+ grep "failed to download bundle from URI" err
54
+'
55
+
56
+test_expect_success 'fail to fetch from non-bundle HTTP URL' '
57
+ test_when_finished rm -rf test &&
58
+ echo bogus >"$HTTPD_DOCUMENT_ROOT_PATH/bogus" &&
59
+ git clone --bundle-uri="$HTTPD_URL/bogus" . test 2>err &&
60
+ grep "is not a bundle" err
61
+'
62
+
63
+test_expect_success 'clone HTTP bundle' '
64
+ cp clone-from/B.bundle "$HTTPD_DOCUMENT_ROOT_PATH/B.bundle" &&
65
+
66
+ git clone --no-local --mirror clone-from \
67
+ "$HTTPD_DOCUMENT_ROOT_PATH/fetch.git" &&
68
+
69
+ git clone --bundle-uri="$HTTPD_URL/B.bundle" \
70
+ "$HTTPD_URL/smart/fetch.git" clone-http &&
71
+ git -C clone-http rev-parse refs/bundles/topic >actual &&
72
+ git -C clone-from rev-parse topic >expect &&
73
+ test_cmp expect actual &&
74
+
75
+ test_config -C clone-http log.excludedecoration refs/bundle/
76
+'
77
+
78
+# Do not add tests here unless they use the HTTP server, as they will
79
+# not run unless the HTTP dependencies exist.
80
+
81
test_done