@@ -7,6 +7,7 @@
#include "run-command.h"
#include "hashmap.h"
#include "pkt-line.h"
+#include "remote.h"
static int compare_bundles(const void *hashmap_cmp_fn_data,
const struct hashmap_entry *he1,
@@ -49,6 +50,7 @@ void clear_bundle_list(struct bundle_list *list)
for_all_bundles_in_list(list, clear_remote_bundle_info, NULL);
hashmap_clear_and_free(&list->bundles, struct remote_bundle_info, ent);
+ free(list->baseURI);
}
int for_all_bundles_in_list(struct bundle_list *list,
@@ -169,7 +171,7 @@ static int bundle_list_update(const char *key, const char *value,
if (!strcmp(dot, "uri")) {
free(bundle->uri);
- bundle->uri = xstrdup(value);
+ bundle->uri = relative_url(list->baseURI, value, NULL);
return 0;
}
@@ -197,6 +199,8 @@ int parse_bundle_list_in_config_format(const char *uri,
};
list->mode = BUNDLE_MODE_NONE;
+ if (!list->baseURI)
+ list->baseURI = xstrdup(uri);
result = git_config_from_file_with_options(config_to_bundle_list,
filename, list,
&opts);
@@ -65,6 +65,15 @@ struct bundle_list {
enum bundle_list_mode mode;
unsigned forFetch : 1;
struct hashmap bundles;
+
+ /**
+ * The baseURI of a bundle_list is used as the base for any
+ * relative URIs advertised by the bundle list at that location.
+ *
+ * When the list is generated from a Git server, then use that
+ * server's location.
+ */
+ char *baseURI;
};
void init_bundle_list(struct bundle_list *list);
@@ -35,6 +35,8 @@ static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mo
init_bundle_list(&list);
+ list.baseURI = xstrdup("<uri>");
+
switch (mode) {
case KEY_VALUE_PAIRS:
if (argc)
@@ -30,6 +30,30 @@ test_expect_success 'bundle_uri_parse_line() just URIs' '
test_cmp_config_output expect actual
'
+test_expect_success 'bundle_uri_parse_line(): relative URIs' '
+ cat >in <<-\EOF &&
+ bundle.one.uri=bundle.bdl
+ bundle.two.uri=../bundle.bdl
+ bundle.three.uri=sub/dir/bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle "list"]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = <uri>/bundle.bdl
+ [bundle "two"]
+ uri = bundle.bdl
+ [bundle "three"]
+ uri = <uri>/sub/dir/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-key-values <in >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
test_expect_success 'bundle_uri_parse_line() parsing edge cases: empty key or value' '
cat >in <<-\EOF &&
=bogus-value
@@ -106,6 +130,36 @@ test_expect_success 'parse config format: just URIs' '
test_cmp_config_output expect actual
'
+test_expect_success 'parse config format: relative URIs' '
+ cat >in <<-\EOF &&
+ [bundle "list"]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = bundle.bdl
+ [bundle "two"]
+ uri = ../bundle.bdl
+ [bundle "three"]
+ uri = sub/dir/bundle.bdl
+ EOF
+
+ cat >expect <<-\EOF &&
+ [bundle "list"]
+ version = 1
+ mode = all
+ [bundle "one"]
+ uri = <uri>/bundle.bdl
+ [bundle "two"]
+ uri = bundle.bdl
+ [bundle "three"]
+ uri = <uri>/sub/dir/bundle.bdl
+ EOF
+
+ test-tool bundle-uri parse-config in >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp_config_output expect actual
+'
+
test_expect_success 'parse config format edge cases: empty key or value' '
cat >in1 <<-\EOF &&
= bogus-value
@@ -1544,6 +1544,9 @@ int transport_get_remote_bundle_uri(struct transport *transport, int quiet)
(git_config_get_bool("transfer.bundleuri", &value) || !value))
return 0;
+ if (!transport->bundles->baseURI)
+ transport->bundles->baseURI = xstrdup(transport->url);
+
if (!vtable->get_bundle_uri) {
if (quiet)
return -1;