From 8262aaa2835d71b0cdf44e68712703a452761328 Mon Sep 17 00:00:00 2001 From: Matthieu Moy Date: Thu, 7 Aug 2014 04:59:12 -0700 Subject: config.c: mark error and warnings strings for translation Signed-off-by: Matthieu Moy Reviewed-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index d3ad661fca..300d626018 100644 --- a/config.c +++ b/config.c @@ -457,9 +457,9 @@ static int git_parse_source(config_fn_t fn, void *data) break; } if (cf->die_on_error) - die("bad config file line %d in %s", cf->linenr, cf->name); + die(_("bad config file line %d in %s"), cf->linenr, cf->name); else - return error("bad config file line %d in %s", cf->linenr, cf->name); + return error(_("bad config file line %d in %s"), cf->linenr, cf->name); } static int parse_unit_factor(const char *end, uintmax_t *val) @@ -575,9 +575,9 @@ static void die_bad_number(const char *name, const char *value) value = ""; if (cf && cf->name) - die("bad numeric config value '%s' for '%s' in %s: %s", + die(_("bad numeric config value '%s' for '%s' in %s: %s"), value, name, cf->name, reason); - die("bad numeric config value '%s' for '%s': %s", value, name, reason); + die(_("bad numeric config value '%s' for '%s': %s"), value, name, reason); } int git_config_int(const char *name, const char *value) @@ -662,7 +662,7 @@ int git_config_pathname(const char **dest, const char *var, const char *value) return config_error_nonbool(var); *dest = expand_user_path(value); if (!*dest) - die("Failed to expand user dir in: '%s'", value); + die(_("failed to expand user dir in: '%s'"), value); return 0; } @@ -740,7 +740,7 @@ static int git_default_core_config(const char *var, const char *value) if (level == -1) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) - die("bad zlib compression level %d", level); + die(_("bad zlib compression level %d"), level); zlib_compression_level = level; zlib_compression_seen = 1; return 0; @@ -751,7 +751,7 @@ static int git_default_core_config(const char *var, const char *value) if (level == -1) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) - die("bad zlib compression level %d", level); + die(_("bad zlib compression level %d"), level); core_compression_level = level; core_compression_seen = 1; if (!zlib_compression_seen) @@ -875,7 +875,7 @@ static int git_default_core_config(const char *var, const char *value) else if (!strcmp(value, "link")) object_creation_mode = OBJECT_CREATION_USES_HARDLINKS; else - die("Invalid mode for object creation: %s", value); + die(_("invalid mode for object creation: %s"), value); return 0; } @@ -1175,7 +1175,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config) switch (git_config_from_parameters(fn, data)) { case -1: /* error */ - die("unable to parse command-line config"); + die(_("unable to parse command-line config")); break; case 0: /* found nothing */ break; @@ -1516,7 +1516,7 @@ static int store_aux(const char *key, const char *value, void *cb) case KEY_SEEN: if (matches(key, value)) { if (store.seen == 1 && store.multi_replace == 0) { - warning("%s has multiple values", key); + warning(_("%s has multiple values"), key); } ALLOC_GROW(store.offset, store.seen + 1, -- cgit v1.2.1 From b3b3f60bb672d23b9db1582395a1d29561cb79ef Mon Sep 17 00:00:00 2001 From: Matthieu Moy Date: Thu, 7 Aug 2014 04:59:13 -0700 Subject: config.c: fix accuracy of line number in errors If a callback returns a negative value to `git_config*()` family, they call `die()` while printing the line number and the file name. Currently the printed line number is off by one, thus printing the wrong line number. Make `linenr` point to the line we just parsed during the call to callback to get accurate line number in error messages. Commit-message-by: Tanay Abhra Signed-off-by: Tanay Abhra Signed-off-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'config.c') diff --git a/config.c b/config.c index 300d626018..22fef4050b 100644 --- a/config.c +++ b/config.c @@ -244,6 +244,7 @@ static int get_next_char(void) cf->linenr++; if (c == EOF) { cf->eof = 1; + cf->linenr++; c = '\n'; } return c; @@ -319,6 +320,7 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name) { int c; char *value; + int ret; /* Get the full name */ for (;;) { @@ -341,7 +343,15 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name) if (!value) return -1; } - return fn(name->buf, value, data); + /* + * We already consumed the \n, but we need linenr to point to + * the line we just parsed during the call to fn to get + * accurate line number in error messages. + */ + cf->linenr--; + ret = fn(name->buf, value, data); + cf->linenr++; + return ret; } static int get_extended_base_var(struct strbuf *name, int c) -- cgit v1.2.1 From 3df8fd625fba33a6525f61c85de39afb746db9bd Mon Sep 17 00:00:00 2001 From: Tanay Abhra Date: Thu, 7 Aug 2014 04:59:14 -0700 Subject: add line number and file name info to `config_set` Store file name and line number for each key-value pair in the cache during parsing of the configuration files. Signed-off-by: Tanay Abhra Reviewed-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 22fef4050b..1ac85edce4 100644 --- a/config.c +++ b/config.c @@ -1262,6 +1262,9 @@ static struct config_set_element *configset_find_element(struct config_set *cs, static int configset_add_value(struct config_set *cs, const char *key, const char *value) { struct config_set_element *e; + struct string_list_item *si; + struct key_value_info *kv_info = xmalloc(sizeof(*kv_info)); + e = configset_find_element(cs, key); /* * Since the keys are being fed by git_config*() callback mechanism, they @@ -1274,7 +1277,16 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha string_list_init(&e->value_list, 1); hashmap_add(&cs->config_hash, e); } - string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL); + si = string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL); + if (cf) { + kv_info->filename = strintern(cf->name); + kv_info->linenr = cf->linenr; + } else { + /* for values read from `git_config_from_parameters()` */ + kv_info->filename = NULL; + kv_info->linenr = -1; + } + si->util = kv_info; return 0; } @@ -1301,7 +1313,7 @@ void git_configset_clear(struct config_set *cs) hashmap_iter_init(&cs->config_hash, &iter); while ((entry = hashmap_iter_next(&iter))) { free(entry->key); - string_list_clear(&entry->value_list, 0); + string_list_clear(&entry->value_list, 1); } hashmap_free(&cs->config_hash, 1); cs->hash_initialized = 0; -- cgit v1.2.1 From aace4385027b0366f43961a94c8ed95ac9b3bd53 Mon Sep 17 00:00:00 2001 From: Tanay Abhra Date: Thu, 7 Aug 2014 04:59:15 -0700 Subject: change `git_config()` return value to void Currently `git_config()` returns an integer signifying an error code. During rewrites of the function most of the code was shifted to `git_config_with_options()`. `git_config_with_options()` normally returns positive values if its `config_source` parameter is set as NULL, as most errors are fatal, and non-fatal potential errors are guarded by "if" statements that are entered only when no error is possible. Still a negative value can be returned in case of race condition between `access_or_die()` & `git_config_from_file()`. Also, all callers of `git_config()` ignore the return value except for one case in branch.c. Change `git_config()` return value to void and make it die if it receives a negative value from `git_config_with_options()`. Original-patch-by: Matthieu Moy Signed-off-by: Tanay Abhra Reviewed-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 1ac85edce4..cd59c4a0f2 100644 --- a/config.c +++ b/config.c @@ -1232,9 +1232,21 @@ int git_config_with_options(config_fn_t fn, void *data, return ret; } -int git_config(config_fn_t fn, void *data) +void git_config(config_fn_t fn, void *data) { - return git_config_with_options(fn, data, NULL, 1); + if (git_config_with_options(fn, data, NULL, 1) < 0) + /* + * git_config_with_options() normally returns only + * positive values, as most errors are fatal, and + * non-fatal potential errors are guarded by "if" + * statements that are entered only when no error is + * possible. + * + * If we ever encounter a non-fatal error, it means + * something went really wrong and we should stop + * immediately. + */ + die(_("unknown error occured while reading the configuration files")); } static struct config_set_element *configset_find_element(struct config_set *cs, const char *key) -- cgit v1.2.1 From 5a80e97c827e9d73884dbe4119bf97f6dd84b237 Mon Sep 17 00:00:00 2001 From: Tanay Abhra Date: Thu, 7 Aug 2014 04:59:16 -0700 Subject: config: add `git_die_config()` to the config-set API Add `git_die_config` that dies printing the line number and the file name of the highest priority value for the configuration variable `key`. A custom error message is also printed before dying, specified by the caller, which can be skipped if `err` argument is set to NULL. It has usage in non-callback based config value retrieval where we can raise an error and die if there is a semantic error. For example, if (!git_config_get_value(key, &value)){ if (!strcmp(value, "foo")) git_config_die(key, "value: `%s` is illegal", value); else /* do work */ } Signed-off-by: Tanay Abhra Reviewed-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index cd59c4a0f2..8449a8ac45 100644 --- a/config.c +++ b/config.c @@ -1471,8 +1471,12 @@ const struct string_list *git_config_get_value_multi(const char *key) int git_config_get_string_const(const char *key, const char **dest) { + int ret; git_config_check_init(); - return git_configset_get_string_const(&the_config_set, key, dest); + ret = git_configset_get_string_const(&the_config_set, key, dest); + if (ret < 0) + git_die_config(key, NULL); + return ret; } int git_config_get_string(const char *key, char **dest) @@ -1513,8 +1517,39 @@ int git_config_get_maybe_bool(const char *key, int *dest) int git_config_get_pathname(const char *key, const char **dest) { + int ret; git_config_check_init(); - return git_configset_get_pathname(&the_config_set, key, dest); + ret = git_configset_get_pathname(&the_config_set, key, dest); + if (ret < 0) + git_die_config(key, NULL); + return ret; +} + +NORETURN +void git_die_config_linenr(const char *key, const char *filename, int linenr) +{ + if (!filename) + die(_("unable to parse '%s' from command-line config"), key); + else + die(_("bad config variable '%s' in file '%s' at line %d"), + key, filename, linenr); +} + +NORETURN __attribute__((format(printf, 2, 3))) +void git_die_config(const char *key, const char *err, ...) +{ + const struct string_list *values; + struct key_value_info *kv_info; + + if (err) { + va_list params; + va_start(params, err); + vreportf("error: ", err, params); + va_end(params); + } + values = git_config_get_value_multi(key); + kv_info = values->items[values->nr - 1].util; + git_die_config_linenr(key, kv_info->filename, kv_info->linenr); } /* -- cgit v1.2.1 From 155ef25f12329258c06b8875b5e372abec2d348d Mon Sep 17 00:00:00 2001 From: Tanay Abhra Date: Thu, 7 Aug 2014 04:59:17 -0700 Subject: rewrite git_config() to use the config-set API Of all the functions in `git_config*()` family, `git_config()` has the most invocations in the whole code base. Each `git_config()` invocation causes config file rereads which can be avoided using the config-set API. Use the config-set API to rewrite `git_config()` to use the config caching layer to avoid config file rereads on each invocation during a git process lifetime. First invocation constructs the cache, and after that for each successive invocation, `git_config()` feeds values from the config cache instead of rereading the configuration files. Signed-off-by: Tanay Abhra Reviewed-by: Matthieu Moy Signed-off-by: Junio C Hamano --- config.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 8449a8ac45..387e86bb6c 100644 --- a/config.c +++ b/config.c @@ -35,12 +35,6 @@ struct config_source { long (*do_ftell)(struct config_source *c); }; -struct config_set_element { - struct hashmap_entry ent; - char *key; - struct string_list value_list; -}; - static struct config_source *cf; static int zlib_compression_seen; @@ -1232,7 +1226,7 @@ int git_config_with_options(config_fn_t fn, void *data, return ret; } -void git_config(config_fn_t fn, void *data) +static void git_config_raw(config_fn_t fn, void *data) { if (git_config_with_options(fn, data, NULL, 1) < 0) /* @@ -1249,6 +1243,33 @@ void git_config(config_fn_t fn, void *data) die(_("unknown error occured while reading the configuration files")); } +static void configset_iter(struct config_set *cs, config_fn_t fn, void *data) +{ + int i, value_index; + struct string_list *values; + struct config_set_element *entry; + struct configset_list *list = &cs->list; + struct key_value_info *kv_info; + + for (i = 0; i < list->nr; i++) { + entry = list->items[i].e; + value_index = list->items[i].value_index; + values = &entry->value_list; + if (fn(entry->key, values->items[value_index].string, data) < 0) { + kv_info = values->items[value_index].util; + git_die_config_linenr(entry->key, kv_info->filename, kv_info->linenr); + } + } +} + +static void git_config_check_init(void); + +void git_config(config_fn_t fn, void *data) +{ + git_config_check_init(); + configset_iter(&the_config_set, fn, data); +} + static struct config_set_element *configset_find_element(struct config_set *cs, const char *key) { struct config_set_element k; @@ -1275,6 +1296,7 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha { struct config_set_element *e; struct string_list_item *si; + struct configset_list_item *l_item; struct key_value_info *kv_info = xmalloc(sizeof(*kv_info)); e = configset_find_element(cs, key); @@ -1290,6 +1312,12 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha hashmap_add(&cs->config_hash, e); } si = string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL); + + ALLOC_GROW(cs->list.items, cs->list.nr + 1, cs->list.alloc); + l_item = &cs->list.items[cs->list.nr++]; + l_item->e = e; + l_item->value_index = e->value_list.nr - 1; + if (cf) { kv_info->filename = strintern(cf->name); kv_info->linenr = cf->linenr; @@ -1313,6 +1341,9 @@ void git_configset_init(struct config_set *cs) { hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp, 0); cs->hash_initialized = 1; + cs->list.nr = 0; + cs->list.alloc = 0; + cs->list.items = NULL; } void git_configset_clear(struct config_set *cs) @@ -1329,6 +1360,10 @@ void git_configset_clear(struct config_set *cs) } hashmap_free(&cs->config_hash, 1); cs->hash_initialized = 0; + free(cs->list.items); + cs->list.nr = 0; + cs->list.alloc = 0; + cs->list.items = NULL; } static int config_set_callback(const char *key, const char *value, void *cb) @@ -1447,7 +1482,7 @@ static void git_config_check_init(void) if (the_config_set.hash_initialized) return; git_configset_init(&the_config_set); - git_config(config_set_callback, &the_config_set); + git_config_raw(config_set_callback, &the_config_set); } void git_config_clear(void) -- cgit v1.2.1