Skip to content

Commit ebc3947

Browse files
derrickstoleegitster
authored andcommitted
bundle-uri: allow relative URLs in bundle lists
Bundle providers may want to distribute that data across multiple CDNs. This might require a change in the base URI, all the way to the domain name. If all bundles require an absolute URI in their 'uri' value, then every push to a CDN would require altering the table of contents to match the expected domain and exact location within it. Allow a bundle list to specify a relative URI for the bundles. This URI is based on where the client received the bundle list. For a list provided in the 'bundle-uri' protocol v2 command, the Git remote URI is the base URI. Otherwise, the bundle list was provided from an HTTP URI not using the Git protocol, and that URI is the base URI. This allows easier distribution of bundle data. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9ea5796 commit ebc3947

File tree

5 files changed

+116
-1
lines changed

5 files changed

+116
-1
lines changed

bundle-uri.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "hashmap.h"
88
#include "pkt-line.h"
99
#include "config.h"
10+
#include "remote.h"
1011

1112
static int compare_bundles(const void *hashmap_cmp_fn_data,
1213
const struct hashmap_entry *he1,
@@ -49,6 +50,7 @@ void clear_bundle_list(struct bundle_list *list)
4950

5051
for_all_bundles_in_list(list, clear_remote_bundle_info, NULL);
5152
hashmap_clear_and_free(&list->bundles, struct remote_bundle_info, ent);
53+
free(list->baseURI);
5254
}
5355

5456
int for_all_bundles_in_list(struct bundle_list *list,
@@ -163,7 +165,7 @@ static int bundle_list_update(const char *key, const char *value,
163165
if (!strcmp(subkey, "uri")) {
164166
if (bundle->uri)
165167
return -1;
166-
bundle->uri = xstrdup(value);
168+
bundle->uri = relative_url(list->baseURI, value, NULL);
167169
return 0;
168170
}
169171

@@ -190,6 +192,18 @@ int bundle_uri_parse_config_format(const char *uri,
190192
.error_action = CONFIG_ERROR_ERROR,
191193
};
192194

195+
if (!list->baseURI) {
196+
struct strbuf baseURI = STRBUF_INIT;
197+
strbuf_addstr(&baseURI, uri);
198+
199+
/*
200+
* If the URI does not end with a trailing slash, then
201+
* remove the filename portion of the path. This is
202+
* important for relative URIs.
203+
*/
204+
strbuf_strip_file_from_path(&baseURI);
205+
list->baseURI = strbuf_detach(&baseURI, NULL);
206+
}
193207
result = git_config_from_file_with_options(config_to_bundle_list,
194208
filename, list,
195209
&opts);

bundle-uri.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ struct bundle_list {
6161
int version;
6262
enum bundle_list_mode mode;
6363
struct hashmap bundles;
64+
65+
/**
66+
* The baseURI of a bundle_list is the URI that provided the list.
67+
*
68+
* In the case of the 'bundle-uri' protocol v2 command, the base
69+
* URI is the URI of the Git remote.
70+
*
71+
* Otherwise, the bundle list was downloaded over HTTP from some
72+
* known URI. 'baseURI' is set to that value.
73+
*
74+
* The baseURI is used as the base for any relative URIs
75+
* advertised by the bundle list at that location.
76+
*/
77+
char *baseURI;
6478
};
6579

6680
void init_bundle_list(struct bundle_list *list);

t/helper/test-bundle-uri.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mo
4040

4141
init_bundle_list(&list);
4242

43+
list.baseURI = xstrdup("<uri>");
44+
4345
switch (mode) {
4446
case KEY_VALUE_PAIRS:
4547
if (argc != 1)

t/t5750-bundle-uri-parse.sh

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,58 @@ test_expect_success 'bundle_uri_parse_line() just URIs' '
3030
test_cmp_config_output expect actual
3131
'
3232

33+
test_expect_success 'bundle_uri_parse_line(): relative URIs' '
34+
cat >in <<-\EOF &&
35+
bundle.one.uri=bundle.bdl
36+
bundle.two.uri=../bundle.bdl
37+
bundle.three.uri=sub/dir/bundle.bdl
38+
EOF
39+
40+
cat >expect <<-\EOF &&
41+
[bundle]
42+
version = 1
43+
mode = all
44+
[bundle "one"]
45+
uri = <uri>/bundle.bdl
46+
[bundle "two"]
47+
uri = bundle.bdl
48+
[bundle "three"]
49+
uri = <uri>/sub/dir/bundle.bdl
50+
EOF
51+
52+
test-tool bundle-uri parse-key-values in >actual 2>err &&
53+
test_must_be_empty err &&
54+
test_cmp_config_output expect actual
55+
'
56+
57+
test_expect_success 'bundle_uri_parse_line(): relative URIs and parent paths' '
58+
cat >in <<-\EOF &&
59+
bundle.one.uri=bundle.bdl
60+
bundle.two.uri=../bundle.bdl
61+
bundle.three.uri=../../bundle.bdl
62+
EOF
63+
64+
cat >expect <<-\EOF &&
65+
[bundle]
66+
version = 1
67+
mode = all
68+
[bundle "one"]
69+
uri = <uri>/bundle.bdl
70+
[bundle "two"]
71+
uri = bundle.bdl
72+
[bundle "three"]
73+
uri = <uri>/../bundle.bdl
74+
EOF
75+
76+
# TODO: We would prefer if parsing a bundle list would not cause
77+
# a die() and instead would give a warning and allow the rest of
78+
# a Git command to continue. This test_must_fail is necessary for
79+
# now until the interface for relative_url() allows for reporting
80+
# an error instead of die()ing.
81+
test_must_fail test-tool bundle-uri parse-key-values in >actual 2>err &&
82+
grep "fatal: cannot strip one component off url" err
83+
'
84+
3385
test_expect_success 'bundle_uri_parse_line() parsing edge cases: empty key or value' '
3486
cat >in <<-\EOF &&
3587
=bogus-value
@@ -136,6 +188,36 @@ test_expect_success 'parse config format: just URIs' '
136188
test_cmp_config_output expect actual
137189
'
138190

191+
test_expect_success 'parse config format: relative URIs' '
192+
cat >in <<-\EOF &&
193+
[bundle]
194+
version = 1
195+
mode = all
196+
[bundle "one"]
197+
uri = bundle.bdl
198+
[bundle "two"]
199+
uri = ../bundle.bdl
200+
[bundle "three"]
201+
uri = sub/dir/bundle.bdl
202+
EOF
203+
204+
cat >expect <<-\EOF &&
205+
[bundle]
206+
version = 1
207+
mode = all
208+
[bundle "one"]
209+
uri = <uri>/bundle.bdl
210+
[bundle "two"]
211+
uri = bundle.bdl
212+
[bundle "three"]
213+
uri = <uri>/sub/dir/bundle.bdl
214+
EOF
215+
216+
test-tool bundle-uri parse-config in >actual 2>err &&
217+
test_must_be_empty err &&
218+
test_cmp_config_output expect actual
219+
'
220+
139221
test_expect_success 'parse config format edge cases: empty key or value' '
140222
cat >in1 <<-\EOF &&
141223
= bogus-value

transport.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,9 @@ int transport_get_remote_bundle_uri(struct transport *transport)
15381538
if (git_config_get_bool("transfer.bundleuri", &value) || !value)
15391539
return 0;
15401540

1541+
if (!transport->bundles->baseURI)
1542+
transport->bundles->baseURI = xstrdup(transport->url);
1543+
15411544
if (!vtable->get_bundle_uri)
15421545
return error(_("bundle-uri operation not supported by protocol"));
15431546

0 commit comments

Comments
 (0)