diff --git a/config.c b/config.c index 3756322ec9..46c5a9a7d5 100644 --- a/config.c +++ b/config.c @@ -1311,39 +1311,48 @@ int git_parse_ssize_t(const char *value, ssize_t *ret) return 1; } +static int reader_config_name(struct config_reader *reader, const char **out); +static int reader_origin_type(struct config_reader *reader, + enum config_origin_type *type); NORETURN -static void die_bad_number(struct config_source *cf, const char *name, +static void die_bad_number(struct config_reader *reader, const char *name, const char *value) { const char *error_type = (errno == ERANGE) ? N_("out of range") : N_("invalid unit"); const char *bad_numeric = N_("bad numeric config value '%s' for '%s': %s"); + const char *config_name = NULL; + enum config_origin_type config_origin = CONFIG_ORIGIN_UNKNOWN; if (!value) value = ""; - if (!(cf && cf->name)) + /* Ignoring the return value is okay since we handle missing values. */ + reader_config_name(reader, &config_name); + reader_origin_type(reader, &config_origin); + + if (!config_name) die(_(bad_numeric), value, name, _(error_type)); - switch (cf->origin_type) { + switch (config_origin) { case CONFIG_ORIGIN_BLOB: die(_("bad numeric config value '%s' for '%s' in blob %s: %s"), - value, name, cf->name, _(error_type)); + value, name, config_name, _(error_type)); case CONFIG_ORIGIN_FILE: die(_("bad numeric config value '%s' for '%s' in file %s: %s"), - value, name, cf->name, _(error_type)); + value, name, config_name, _(error_type)); case CONFIG_ORIGIN_STDIN: die(_("bad numeric config value '%s' for '%s' in standard input: %s"), value, name, _(error_type)); case CONFIG_ORIGIN_SUBMODULE_BLOB: die(_("bad numeric config value '%s' for '%s' in submodule-blob %s: %s"), - value, name, cf->name, _(error_type)); + value, name, config_name, _(error_type)); case CONFIG_ORIGIN_CMDLINE: die(_("bad numeric config value '%s' for '%s' in command line %s: %s"), - value, name, cf->name, _(error_type)); + value, name, config_name, _(error_type)); default: die(_("bad numeric config value '%s' for '%s' in %s: %s"), - value, name, cf->name, _(error_type)); + value, name, config_name, _(error_type)); } } @@ -1351,7 +1360,7 @@ int git_config_int(const char *name, const char *value) { int ret; if (!git_parse_int(value, &ret)) - die_bad_number(the_reader.source, name, value); + die_bad_number(&the_reader, name, value); return ret; } @@ -1359,7 +1368,7 @@ int64_t git_config_int64(const char *name, const char *value) { int64_t ret; if (!git_parse_int64(value, &ret)) - die_bad_number(the_reader.source, name, value); + die_bad_number(&the_reader, name, value); return ret; } @@ -1367,7 +1376,7 @@ unsigned long git_config_ulong(const char *name, const char *value) { unsigned long ret; if (!git_parse_ulong(value, &ret)) - die_bad_number(the_reader.source, name, value); + die_bad_number(&the_reader, name, value); return ret; } @@ -1375,7 +1384,7 @@ ssize_t git_config_ssize_t(const char *name, const char *value) { ssize_t ret; if (!git_parse_ssize_t(value, &ret)) - die_bad_number(the_reader.source, name, value); + die_bad_number(&the_reader, name, value); return ret; } @@ -3839,14 +3848,23 @@ int parse_config_key(const char *var, return 0; } +static int reader_origin_type(struct config_reader *reader, + enum config_origin_type *type) +{ + if (the_reader.config_kvi) + *type = reader->config_kvi->origin_type; + else if(the_reader.source) + *type = reader->source->origin_type; + else + return 1; + return 0; +} + const char *current_config_origin_type(void) { - int type; - if (the_reader.config_kvi) - type = the_reader.config_kvi->origin_type; - else if(the_reader.source) - type = the_reader.source->origin_type; - else + enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN; + + if (reader_origin_type(&the_reader, &type)) BUG("current_config_origin_type called outside config callback"); switch (type) { @@ -3885,14 +3903,21 @@ const char *config_scope_name(enum config_scope scope) } } +static int reader_config_name(struct config_reader *reader, const char **out) +{ + if (the_reader.config_kvi) + *out = reader->config_kvi->filename; + else if (the_reader.source) + *out = reader->source->name; + else + return 1; + return 0; +} + const char *current_config_name(void) { const char *name; - if (the_reader.config_kvi) - name = the_reader.config_kvi->filename; - else if (the_reader.source) - name = the_reader.source->name; - else + if (reader_config_name(&the_reader, &name)) BUG("current_config_name called outside config callback"); return name ? name : ""; } diff --git a/config.h b/config.h index 7606246531..66c8b996e1 100644 --- a/config.h +++ b/config.h @@ -56,6 +56,7 @@ struct git_config_source { }; enum config_origin_type { + CONFIG_ORIGIN_UNKNOWN = 0, CONFIG_ORIGIN_BLOB, CONFIG_ORIGIN_FILE, CONFIG_ORIGIN_STDIN, diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 4ba9eb6560..26e79168f6 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -30,6 +30,9 @@ * iterate -> iterate over all values using git_config(), and print some * data for each * + * git_config_int -> iterate over all values using git_config() and print the + * integer value for the entered key or die + * * Examples: * * 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) return 0; } +static int parse_int_cb(const char *var, const char *value, void *data) +{ + const char *key_to_match = data; + + if (!strcmp(key_to_match, var)) { + int parsed = git_config_int(value, value); + printf("%d\n", parsed); + } + return 0; +} + static int early_config_cb(const char *var, const char *value, void *vdata) { const char *key = vdata; @@ -176,6 +190,9 @@ int cmd__config(int argc, const char **argv) } else if (!strcmp(argv[1], "iterate")) { git_config(iterate_cb, NULL); goto exit0; + } else if (argc == 3 && !strcmp(argv[1], "git_config_int")) { + git_config(parse_int_cb, (void *) argv[2]); + goto exit0; } die("%s: Please check the syntax and the function name", argv[0]); diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index b38e158d3b..9733bed30a 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -120,6 +120,10 @@ test_expect_success 'find integer value for a key' ' check_config get_int lamb.chop 65 ' +test_expect_success 'parse integer value during iteration' ' + check_config git_config_int lamb.chop 65 +' + test_expect_success 'find string value for a key' ' check_config get_string case.baz hask && 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' ' check_config expect_code 128 get_int lamb.head ' +test_expect_success 'non parse-able integer value during iteration' ' + check_config expect_code 128 git_config_int lamb.head 2>result && + grep "fatal: bad numeric config value .* in file \.git/config" result +' + test_expect_success 'find bool value for the entered key' ' check_config get_bool goat.head 1 && check_config get_bool goat.skin 0 &&