Skip to content

Commit 3c3460d

Browse files
committed
bundle-uri: parse bundle list in config format
When a bundle provider wants to operate independently from a Git remote, they want to provide a single, consistent URI that users can use in their 'git clone --bundle-uri' commands. At this point, the Git client expects that URI to be a single bundle that can be unbundled and used to bootstrap the rest of the clone from the Git server. This single bundle cannot be re-used to assist with future incremental fetches. To allow for the incremental fetch case, teach Git to understand a bundle list that could be advertised at an independent bundle URI. Such a bundle list is likely to be inspected by human readers, even if only by the bundle provider creating the list. For this reason, we can take our expected "key=value" pairs and instead format them using Git config format. Create parse_bundle_list_in_config_format() to parse a file in config format and convert that into a 'struct bundle_list' filled with its understanding of the contents. Be careful to call git_config_from_file_with_options() because the default action for git_config_from_file() is to die() on a parsing error. The current warning isn't particularly helpful if it arises to a user, but it will be made more verbose at a higher layer later. Update 'test-tool bundle-uri' to take this config file format as input. It uses a filename instead of stdin because there is no existing way to parse a FILE pointer in the config machinery. Using git_config_from_mem() is overly complicated and more likely to introduce bugs than this simpler version. I would rather have a slightly confusing test helper than complicated product code. Signed-off-by: Derrick Stolee <derrickstolee@github.com>
1 parent ee01a85 commit 3c3460d

File tree

4 files changed

+125
-9
lines changed

4 files changed

+125
-9
lines changed

bundle-uri.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "run-command.h"
77
#include "hashmap.h"
88
#include "pkt-line.h"
9+
#include "config.h"
910

1011
static int compare_bundles(const void *hashmap_cmp_fn_data,
1112
const struct hashmap_entry *he1,
@@ -172,6 +173,34 @@ static int bundle_list_update(const char *key, const char *value,
172173
return 0;
173174
}
174175

176+
static int config_to_bundle_list(const char *key, const char *value, void *data)
177+
{
178+
struct bundle_list *list = data;
179+
return bundle_list_update(key, value, list);
180+
}
181+
182+
int parse_bundle_list_in_config_format(const char *uri,
183+
const char *filename,
184+
struct bundle_list *list)
185+
{
186+
int result;
187+
struct config_options opts = {
188+
.error_action = CONFIG_ERROR_ERROR,
189+
};
190+
191+
list->mode = BUNDLE_MODE_NONE;
192+
result = git_config_from_file_with_options(config_to_bundle_list,
193+
filename, list,
194+
&opts);
195+
196+
if (!result && list->mode == BUNDLE_MODE_NONE) {
197+
warning(_("bundle list at '%s' has no mode"), uri);
198+
result = 1;
199+
}
200+
201+
return result;
202+
}
203+
175204
static int find_temp_filename(struct strbuf *name)
176205
{
177206
int fd;

bundle-uri.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ int for_all_bundles_in_list(struct bundle_list *list,
7171
struct FILE;
7272
void print_bundle_list(FILE *fp, struct bundle_list *list);
7373

74+
/**
75+
* A bundle URI may point to a bundle list where the key=value
76+
* pairs are provided in config file format. This method is
77+
* exposed publicly for testing purposes.
78+
*/
79+
80+
int parse_bundle_list_in_config_format(const char *uri,
81+
const char *filename,
82+
struct bundle_list *list);
83+
7484
/**
7585
* Fetch data from the given 'uri' and unbundle the bundle data found
7686
* based on that information.

t/helper/test-bundle-uri.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,52 @@
44
#include "strbuf.h"
55
#include "string-list.h"
66

7-
static int cmd__bundle_uri_parse_key_values(int argc, const char **argv)
7+
enum input_mode {
8+
KEY_VALUE_PAIRS,
9+
CONFIG_FILE,
10+
};
11+
12+
static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mode)
813
{
9-
const char *usage[] = {
14+
const char *key_value_usage[] = {
1015
"test-tool bundle-uri parse-key-values <in",
1116
NULL
1217
};
18+
const char *config_usage[] = {
19+
"test-tool bundle-uri parse-config <input>",
20+
NULL
21+
};
1322
struct option options[] = {
1423
OPT_END(),
1524
};
25+
const char **usage = key_value_usage;
1626
struct strbuf sb = STRBUF_INIT;
1727
struct bundle_list list;
1828
int err = 0;
1929

20-
argc = parse_options(argc, argv, NULL, options, usage, 0);
21-
if (argc)
22-
goto usage;
30+
if (mode == CONFIG_FILE)
31+
usage = config_usage;
32+
33+
argc = parse_options(argc, argv, NULL, options, usage,
34+
PARSE_OPT_STOP_AT_NON_OPTION);
2335

2436
init_bundle_list(&list);
25-
while (strbuf_getline(&sb, stdin) != EOF) {
26-
if (bundle_uri_parse_line(&list, sb.buf) < 0)
27-
err = error("bad line: '%s'", sb.buf);
37+
38+
switch (mode) {
39+
case KEY_VALUE_PAIRS:
40+
if (argc)
41+
goto usage;
42+
while (strbuf_getline(&sb, stdin) != EOF) {
43+
if (bundle_uri_parse_line(&list, sb.buf) < 0)
44+
err = error("bad line: '%s'", sb.buf);
45+
}
46+
break;
47+
48+
case CONFIG_FILE:
49+
if (argc != 1)
50+
goto usage;
51+
err = parse_bundle_list_in_config_format("<uri>", argv[0], &list);
52+
break;
2853
}
2954
strbuf_release(&sb);
3055

@@ -55,7 +80,9 @@ int cmd__bundle_uri(int argc, const char **argv)
5580
goto usage;
5681

5782
if (!strcmp(argv[1], "parse-key-values"))
58-
return cmd__bundle_uri_parse_key_values(argc - 1, argv + 1);
83+
return cmd__bundle_uri_parse(argc - 1, argv + 1, KEY_VALUE_PAIRS);
84+
if (!strcmp(argv[1], "parse-config"))
85+
return cmd__bundle_uri_parse(argc - 1, argv + 1, CONFIG_FILE);
5986
error("there is no test-tool bundle-uri tool '%s'", argv[1]);
6087

6188
usage:

t/t5750-bundle-uri-parse.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,54 @@ test_expect_success 'bundle_uri_parse_line() parsing edge cases: empty lines' '
8888
test_cmp_config_output expect actual
8989
'
9090

91+
test_expect_success 'parse config format: just URIs' '
92+
cat >expect <<-\EOF &&
93+
[bundle]
94+
version = 1
95+
mode = all
96+
[bundle "one"]
97+
uri = http://example.com/bundle.bdl
98+
[bundle "two"]
99+
uri = https://example.com/bundle.bdl
100+
[bundle "three"]
101+
uri = file:///usr/share/git/bundle.bdl
102+
EOF
103+
104+
test-tool bundle-uri parse-config expect >actual 2>err &&
105+
test_must_be_empty err &&
106+
test_cmp_config_output expect actual
107+
'
108+
109+
test_expect_success 'parse config format edge cases: empty key or value' '
110+
cat >in1 <<-\EOF &&
111+
= bogus-value
112+
EOF
113+
114+
cat >err1 <<-EOF &&
115+
error: bad config line 1 in file in1
116+
EOF
117+
118+
cat >expect <<-\EOF &&
119+
[bundle]
120+
version = 1
121+
mode = <unknown>
122+
EOF
123+
124+
test_must_fail test-tool bundle-uri parse-config in1 >actual 2>err &&
125+
test_cmp err1 err &&
126+
test_cmp_config_output expect actual &&
127+
128+
cat >in2 <<-\EOF &&
129+
bogus-key =
130+
EOF
131+
132+
cat >err2 <<-EOF &&
133+
warning: bundle list at '\''<uri>'\'' has no mode
134+
EOF
135+
136+
test_must_fail test-tool bundle-uri parse-config in2 >actual 2>err &&
137+
test_cmp err2 err &&
138+
test_cmp_config_output expect actual
139+
'
140+
91141
test_done

0 commit comments

Comments
 (0)