Skip to content

Commit e201650

Browse files
chooglengitster
authored andcommitted
config: report cached filenames in die_bad_number()
If, when parsing numbers from config, die_bad_number() is called, it reports the filename and config source type if we were parsing a config file, but not if we were iterating a config_set (it defaults to a less specific error message). Most call sites don't parse config files because config is typically read once and cached, so we only report filename and config source type in "git config --type" (since "git config" always parses config files). This could have been fixed when we taught the current_config_* functions to respect config_set values (0d44a2d (config: return configset value for current_config_ functions, 2016-05-26), but it was hard to spot then and we might have just missed it (I didn't find mention of die_bad_number() in the original ML discussion [1].) Fix this by refactoring the current_config_* functions into variants that don't BUG() when we aren't reading config, and using the resulting functions in die_bad_number(). "git config --get[-regexp] --type=int" cannot use the non-refactored version because it parses the int value _after_ parsing the config file, which would run into the BUG(). Since the refactored functions aren't public, they use "struct config_reader". 1. https://lore.kernel.org/git/[email protected]/ Signed-off-by: Glen Choo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5cdf18e commit e201650

File tree

4 files changed

+72
-20
lines changed

4 files changed

+72
-20
lines changed

config.c

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,71 +1311,80 @@ int git_parse_ssize_t(const char *value, ssize_t *ret)
13111311
return 1;
13121312
}
13131313

1314+
static int reader_config_name(struct config_reader *reader, const char **out);
1315+
static int reader_origin_type(struct config_reader *reader,
1316+
enum config_origin_type *type);
13141317
NORETURN
1315-
static void die_bad_number(struct config_source *cf, const char *name,
1318+
static void die_bad_number(struct config_reader *reader, const char *name,
13161319
const char *value)
13171320
{
13181321
const char *error_type = (errno == ERANGE) ?
13191322
N_("out of range") : N_("invalid unit");
13201323
const char *bad_numeric = N_("bad numeric config value '%s' for '%s': %s");
1324+
const char *config_name = NULL;
1325+
enum config_origin_type config_origin = CONFIG_ORIGIN_UNKNOWN;
13211326

13221327
if (!value)
13231328
value = "";
13241329

1325-
if (!(cf && cf->name))
1330+
/* Ignoring the return value is okay since we handle missing values. */
1331+
reader_config_name(reader, &config_name);
1332+
reader_origin_type(reader, &config_origin);
1333+
1334+
if (!config_name)
13261335
die(_(bad_numeric), value, name, _(error_type));
13271336

1328-
switch (cf->origin_type) {
1337+
switch (config_origin) {
13291338
case CONFIG_ORIGIN_BLOB:
13301339
die(_("bad numeric config value '%s' for '%s' in blob %s: %s"),
1331-
value, name, cf->name, _(error_type));
1340+
value, name, config_name, _(error_type));
13321341
case CONFIG_ORIGIN_FILE:
13331342
die(_("bad numeric config value '%s' for '%s' in file %s: %s"),
1334-
value, name, cf->name, _(error_type));
1343+
value, name, config_name, _(error_type));
13351344
case CONFIG_ORIGIN_STDIN:
13361345
die(_("bad numeric config value '%s' for '%s' in standard input: %s"),
13371346
value, name, _(error_type));
13381347
case CONFIG_ORIGIN_SUBMODULE_BLOB:
13391348
die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"),
1340-
value, name, cf->name, _(error_type));
1349+
value, name, config_name, _(error_type));
13411350
case CONFIG_ORIGIN_CMDLINE:
13421351
die(_("bad numeric config value '%s' for '%s' in command line %s: %s"),
1343-
value, name, cf->name, _(error_type));
1352+
value, name, config_name, _(error_type));
13441353
default:
13451354
die(_("bad numeric config value '%s' for '%s' in %s: %s"),
1346-
value, name, cf->name, _(error_type));
1355+
value, name, config_name, _(error_type));
13471356
}
13481357
}
13491358

13501359
int git_config_int(const char *name, const char *value)
13511360
{
13521361
int ret;
13531362
if (!git_parse_int(value, &ret))
1354-
die_bad_number(the_reader.source, name, value);
1363+
die_bad_number(&the_reader, name, value);
13551364
return ret;
13561365
}
13571366

13581367
int64_t git_config_int64(const char *name, const char *value)
13591368
{
13601369
int64_t ret;
13611370
if (!git_parse_int64(value, &ret))
1362-
die_bad_number(the_reader.source, name, value);
1371+
die_bad_number(&the_reader, name, value);
13631372
return ret;
13641373
}
13651374

13661375
unsigned long git_config_ulong(const char *name, const char *value)
13671376
{
13681377
unsigned long ret;
13691378
if (!git_parse_ulong(value, &ret))
1370-
die_bad_number(the_reader.source, name, value);
1379+
die_bad_number(&the_reader, name, value);
13711380
return ret;
13721381
}
13731382

13741383
ssize_t git_config_ssize_t(const char *name, const char *value)
13751384
{
13761385
ssize_t ret;
13771386
if (!git_parse_ssize_t(value, &ret))
1378-
die_bad_number(the_reader.source, name, value);
1387+
die_bad_number(&the_reader, name, value);
13791388
return ret;
13801389
}
13811390

@@ -3839,14 +3848,23 @@ int parse_config_key(const char *var,
38393848
return 0;
38403849
}
38413850

3842-
const char *current_config_origin_type(void)
3851+
static int reader_origin_type(struct config_reader *reader,
3852+
enum config_origin_type *type)
38433853
{
3844-
int type;
38453854
if (the_reader.config_kvi)
3846-
type = the_reader.config_kvi->origin_type;
3855+
*type = reader->config_kvi->origin_type;
38473856
else if(the_reader.source)
3848-
type = the_reader.source->origin_type;
3857+
*type = reader->source->origin_type;
38493858
else
3859+
return 1;
3860+
return 0;
3861+
}
3862+
3863+
const char *current_config_origin_type(void)
3864+
{
3865+
enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN;
3866+
3867+
if (reader_origin_type(&the_reader, &type))
38503868
BUG("current_config_origin_type called outside config callback");
38513869

38523870
switch (type) {
@@ -3885,14 +3903,21 @@ const char *config_scope_name(enum config_scope scope)
38853903
}
38863904
}
38873905

3888-
const char *current_config_name(void)
3906+
static int reader_config_name(struct config_reader *reader, const char **out)
38893907
{
3890-
const char *name;
38913908
if (the_reader.config_kvi)
3892-
name = the_reader.config_kvi->filename;
3909+
*out = reader->config_kvi->filename;
38933910
else if (the_reader.source)
3894-
name = the_reader.source->name;
3911+
*out = reader->source->name;
38953912
else
3913+
return 1;
3914+
return 0;
3915+
}
3916+
3917+
const char *current_config_name(void)
3918+
{
3919+
const char *name;
3920+
if (reader_config_name(&the_reader, &name))
38963921
BUG("current_config_name called outside config callback");
38973922
return name ? name : "";
38983923
}

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct git_config_source {
5656
};
5757

5858
enum config_origin_type {
59+
CONFIG_ORIGIN_UNKNOWN = 0,
5960
CONFIG_ORIGIN_BLOB,
6061
CONFIG_ORIGIN_FILE,
6162
CONFIG_ORIGIN_STDIN,

t/helper/test-config.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
* iterate -> iterate over all values using git_config(), and print some
3131
* data for each
3232
*
33+
* git_config_int -> iterate over all values using git_config() and print the
34+
* integer value for the entered key or die
35+
*
3336
* Examples:
3437
*
3538
* To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -54,6 +57,17 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)
5457
return 0;
5558
}
5659

60+
static int parse_int_cb(const char *var, const char *value, void *data)
61+
{
62+
const char *key_to_match = data;
63+
64+
if (!strcmp(key_to_match, var)) {
65+
int parsed = git_config_int(value, value);
66+
printf("%d\n", parsed);
67+
}
68+
return 0;
69+
}
70+
5771
static int early_config_cb(const char *var, const char *value, void *vdata)
5872
{
5973
const char *key = vdata;
@@ -176,6 +190,9 @@ int cmd__config(int argc, const char **argv)
176190
} else if (!strcmp(argv[1], "iterate")) {
177191
git_config(iterate_cb, NULL);
178192
goto exit0;
193+
} else if (argc == 3 && !strcmp(argv[1], "git_config_int")) {
194+
git_config(parse_int_cb, (void *) argv[2]);
195+
goto exit0;
179196
}
180197

181198
die("%s: Please check the syntax and the function name", argv[0]);

t/t1308-config-set.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ test_expect_success 'find integer value for a key' '
120120
check_config get_int lamb.chop 65
121121
'
122122

123+
test_expect_success 'parse integer value during iteration' '
124+
check_config git_config_int lamb.chop 65
125+
'
126+
123127
test_expect_success 'find string value for a key' '
124128
check_config get_string case.baz hask &&
125129
check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
@@ -134,6 +138,11 @@ test_expect_success 'find integer if value is non parse-able' '
134138
check_config expect_code 128 get_int lamb.head
135139
'
136140

141+
test_expect_success 'non parse-able integer value during iteration' '
142+
check_config expect_code 128 git_config_int lamb.head 2>result &&
143+
grep "fatal: bad numeric config value .* in file \.git/config" result
144+
'
145+
137146
test_expect_success 'find bool value for the entered key' '
138147
check_config get_bool goat.head 1 &&
139148
check_config get_bool goat.skin 0 &&

0 commit comments

Comments
 (0)