Subject: Re: [PATCH v2 7/9] bundle-uri: allow relative URLs in bundle lists

From: Victoria Dye <[email-masked]>
Date: Mon, 28 Nov 2022 17:25:38 -0800

Derrick Stolee via GitGitGadget wrote:
> From: Derrick Stolee <[email-masked]>
> 
> 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 allows easier distribution of bundle data.
> 
> Signed-off-by: Derrick Stolee <[email-masked]>
> ---
>  bundle-uri.c                | 16 ++++++++++-
>  bundle-uri.h                |  9 +++++++
>  t/helper/test-bundle-uri.c  |  2 ++
>  t/t5750-bundle-uri-parse.sh | 54 +++++++++++++++++++++++++++++++++++++
>  transport.c                 |  3 +++
>  5 files changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/bundle-uri.c b/bundle-uri.c
> @@ -190,6 +192,18 @@ int bundle_uri_parse_config_format(const char *uri,
>  		.error_action = CONFIG_ERROR_ERROR,
>  	};
>  
> +	if (!list->baseURI) {
> +		struct strbuf baseURI = STRBUF_INIT;
> +		strbuf_addstr(&baseURI, uri);
> +
> +		/*
> +		 * If the URI does not end with a trailing slash, then
> +		 * remove the filename portion of the path. This is
> +		 * important for relative URIs.
> +		 */
> +		strbuf_strip_file_from_path(&baseURI);
> +		list->baseURI = strbuf_detach(&baseURI, NULL);

Is the 'baseURI' is set to the URI of the first bundle (ordered by hash)? If
data is distributed across multiple CDNs, couldn't this be a suboptimal
choice? For example, if the first bundle is on 'A.com', but every other
bundle is on 'B.org'?

> +	}
>  	result = git_config_from_file_with_options(config_to_bundle_list,
>  						   filename, list,
>  						   &opts);
> diff --git a/bundle-uri.h b/bundle-uri.h
> index 357111ecce8..7905e56732c 100644
> --- a/bundle-uri.h
> +++ b/bundle-uri.h
> @@ -61,6 +61,15 @@ struct bundle_list {
>  	int version;
>  	enum bundle_list_mode mode;
>  	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.

Hmmm, I think I'm missing something with my earlier comment. I thought the
'uri' argument to 'bundle_uri_parse_config_format()' was an individual
bundle's URI? What's the "server's location" in this context?

> +	 */
> +	char *baseURI;
>  };
>  
>  void init_bundle_list(struct bundle_list *list);
> diff --git a/t/helper/test-bundle-uri.c b/t/helper/test-bundle-uri.c
> index ffb975b7b4f..5aa0b494ce3 100644
> --- a/t/helper/test-bundle-uri.c
> +++ b/t/helper/test-bundle-uri.c
> @@ -40,6 +40,8 @@ static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mo
>  
>  	init_bundle_list(&list);
>  
> +	list.baseURI = xstrdup("<uri>");

Using a hardcoded value here leads to pretty different behavior in
'test-bundle-uri.c' vs. starting with an unset 'list.baseURI' in something
like 'clone'. Why does this need to be set to '<uri>' for the tests?

> +
>  	switch (mode) {
>  	case KEY_VALUE_PAIRS:
>  		if (argc != 1)
> diff --git a/t/t5750-bundle-uri-parse.sh b/t/t5750-bundle-uri-parse.sh
> index c2fe3f9c5a5..ed5262a8d2b 100755
> --- a/t/t5750-bundle-uri-parse.sh
> +++ b/t/t5750-bundle-uri-parse.sh
> @@ -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]
> +		version = 1
> +		mode = all
> +	[bundle "one"]
> +		uri = <uri>/bundle.bdl
> +	[bundle "two"]
> +		uri = bundle.bdl

This seems a little strange, but it looks like '<uri>/../bundle.bdl'
normalizes to 'bundle.bdl' because '<uri>' is treated like a regular path
element (like a directory). 

Out of curiosity, what would happen if 'bundle.two.uri' was
'../../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