aboutsummaryrefslogtreecommitdiffstats
path: root/config.c
diff options
context:
space:
mode:
authorGlen Choo <chooglen@google.com>2023-03-28 17:51:53 +0000
committerJunio C Hamano <gitster@pobox.com>2023-03-28 13:03:27 -0700
commite2016508e7690cddc789fb28879703082363549d (patch)
treec3dbcb4ad2e3ccbf681535de87344c43e7eaec1f /config.c
parent5cdf18e7cd6d6e3ce2fb21fef2b5ec84e570abf8 (diff)
downloadgit-e2016508e7690cddc789fb28879703082363549d.tar.gz
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 (0d44a2dacc (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/20160518223712.GA18317@sigill.intra.peff.net/ Signed-off-by: Glen Choo <chooglen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'config.c')
-rw-r--r--config.c65
1 files changed, 45 insertions, 20 deletions
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;
}
-const char *current_config_origin_type(void)
+static int reader_origin_type(struct config_reader *reader,
+ enum config_origin_type *type)
{
- int type;
if (the_reader.config_kvi)
- type = the_reader.config_kvi->origin_type;
+ *type = reader->config_kvi->origin_type;
else if(the_reader.source)
- type = the_reader.source->origin_type;
+ *type = reader->source->origin_type;
else
+ return 1;
+ return 0;
+}
+
+const char *current_config_origin_type(void)
+{
+ 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)
}
}
-const char *current_config_name(void)
+static int reader_config_name(struct config_reader *reader, const char **out)
{
- const char *name;
if (the_reader.config_kvi)
- name = the_reader.config_kvi->filename;
+ *out = reader->config_kvi->filename;
else if (the_reader.source)
- name = the_reader.source->name;
+ *out = reader->source->name;
else
+ return 1;
+ return 0;
+}
+
+const char *current_config_name(void)
+{
+ const char *name;
+ if (reader_config_name(&the_reader, &name))
BUG("current_config_name called outside config callback");
return name ? name : "";
}