Skip to content

Commit 738e524

Browse files
derrickstoleegitster
authored andcommitted
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 bundle_uri_parse_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 use error_action CONFIG_ERROR_ERROR when calling 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. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d796ced commit 738e524

File tree

4 files changed

+123
-12
lines changed

4 files changed

+123
-12
lines changed

bundle-uri.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,33 @@ static int bundle_list_update(const char *key, const char *value,
173173
return 0;
174174
}
175175

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 bundle_uri_parse_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+
result = git_config_from_file_with_options(config_to_bundle_list,
192+
filename, list,
193+
&opts);
194+
195+
if (!result && list->mode == BUNDLE_MODE_NONE) {
196+
warning(_("bundle list at '%s' has no mode"), uri);
197+
result = 1;
198+
}
199+
200+
return result;
201+
}
202+
176203
static char *find_temp_filename(void)
177204
{
178205
int fd;

bundle-uri.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ int for_all_bundles_in_list(struct bundle_list *list,
6262
struct FILE;
6363
void print_bundle_list(FILE *fp, struct bundle_list *list);
6464

65+
/**
66+
* A bundle URI may point to a bundle list where the key=value
67+
* pairs are provided in config file format. This method is
68+
* exposed publicly for testing purposes.
69+
*/
70+
int bundle_uri_parse_config_format(const char *uri,
71+
const char *filename,
72+
struct bundle_list *list);
73+
6574
/**
6675
* Fetch data from the given 'uri' and unbundle the bundle data found
6776
* based on that information.

t/helper/test-bundle-uri.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44
#include "strbuf.h"
55
#include "string-list.h"
66

7-
static int cmd__bundle_uri_parse(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
{
914
const char *key_value_usage[] = {
1015
"test-tool bundle-uri parse-key-values <input>",
1116
NULL
1217
};
18+
const char *config_usage[] = {
19+
"test-tool bundle-uri parse-config <input>",
20+
NULL
21+
};
1322
const char **usage = key_value_usage;
1423
struct option options[] = {
1524
OPT_END(),
@@ -19,21 +28,35 @@ static int cmd__bundle_uri_parse(int argc, const char **argv)
1928
int err = 0;
2029
FILE *fp;
2130

22-
argc = parse_options(argc, argv, NULL, options, usage, 0);
23-
if (argc != 1)
24-
goto usage;
31+
if (mode == CONFIG_FILE)
32+
usage = config_usage;
33+
34+
argc = parse_options(argc, argv, NULL, options, usage,
35+
PARSE_OPT_STOP_AT_NON_OPTION);
2536

2637
init_bundle_list(&list);
27-
fp = fopen(argv[0], "r");
28-
if (!fp)
29-
die("failed to open '%s'", argv[0]);
3038

31-
while (strbuf_getline(&sb, fp) != EOF) {
32-
if (bundle_uri_parse_line(&list, sb.buf))
33-
err = error("bad line: '%s'", sb.buf);
39+
switch (mode) {
40+
case KEY_VALUE_PAIRS:
41+
if (argc != 1)
42+
goto usage;
43+
fp = fopen(argv[0], "r");
44+
if (!fp)
45+
die("failed to open '%s'", argv[0]);
46+
while (strbuf_getline(&sb, fp) != EOF) {
47+
if (bundle_uri_parse_line(&list, sb.buf))
48+
err = error("bad line: '%s'", sb.buf);
49+
}
50+
fclose(fp);
51+
break;
52+
53+
case CONFIG_FILE:
54+
if (argc != 1)
55+
goto usage;
56+
err = bundle_uri_parse_config_format("<uri>", argv[0], &list);
57+
break;
3458
}
3559
strbuf_release(&sb);
36-
fclose(fp);
3760

3861
print_bundle_list(stdout, &list);
3962

@@ -62,7 +85,9 @@ int cmd__bundle_uri(int argc, const char **argv)
6285
goto usage;
6386

6487
if (!strcmp(argv[1], "parse-key-values"))
65-
return cmd__bundle_uri_parse(argc - 1, argv + 1);
88+
return cmd__bundle_uri_parse(argc - 1, argv + 1, KEY_VALUE_PAIRS);
89+
if (!strcmp(argv[1], "parse-config"))
90+
return cmd__bundle_uri_parse(argc - 1, argv + 1, CONFIG_FILE);
6691
error("there is no test-tool bundle-uri tool '%s'", argv[1]);
6792

6893
usage:

t/t5750-bundle-uri-parse.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,54 @@ test_expect_success 'bundle_uri_parse_line() parsing edge cases: duplicate lines
118118
test_cmp_config_output expect actual
119119
'
120120

121+
test_expect_success 'parse config format: just URIs' '
122+
cat >expect <<-\EOF &&
123+
[bundle]
124+
version = 1
125+
mode = all
126+
[bundle "one"]
127+
uri = http://example.com/bundle.bdl
128+
[bundle "two"]
129+
uri = https://example.com/bundle.bdl
130+
[bundle "three"]
131+
uri = file:///usr/share/git/bundle.bdl
132+
EOF
133+
134+
test-tool bundle-uri parse-config expect >actual 2>err &&
135+
test_must_be_empty err &&
136+
test_cmp_config_output expect actual
137+
'
138+
139+
test_expect_success 'parse config format edge cases: empty key or value' '
140+
cat >in1 <<-\EOF &&
141+
= bogus-value
142+
EOF
143+
144+
cat >err1 <<-EOF &&
145+
error: bad config line 1 in file in1
146+
EOF
147+
148+
cat >expect <<-\EOF &&
149+
[bundle]
150+
version = 1
151+
mode = all
152+
EOF
153+
154+
test_must_fail test-tool bundle-uri parse-config in1 >actual 2>err &&
155+
test_cmp err1 err &&
156+
test_cmp_config_output expect actual &&
157+
158+
cat >in2 <<-\EOF &&
159+
bogus-key =
160+
EOF
161+
162+
cat >err2 <<-EOF &&
163+
error: bad config line 1 in file in2
164+
EOF
165+
166+
test_must_fail test-tool bundle-uri parse-config in2 >actual 2>err &&
167+
test_cmp err2 err &&
168+
test_cmp_config_output expect actual
169+
'
170+
121171
test_done

0 commit comments

Comments
 (0)