* [PATCH v9 0/8] Rewrite `git_config()` using config-set API
@ 2014-08-07 11:59 Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 1/8] config.c: mark error and warnings strings for translation Tanay Abhra
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
[Patch v9]: Changed the grep statements in patch 7/8 and 8/8.
[Patch v8]: git_die_config now allows custom error messages.
new tests are now not too reliant on specific strings.
[Patch v7]: style nit corrected. (1/8) is Matthieu's translation patch.
git_die_config_linenr() helper function added. Diff between v6
and v7 appended for review.
[Patch v6]: Added _(....) to error messages.
Diff between v6 and v4 at the bottom.
[PATCH v5]: New patch added (3/7). git_config() now returns void.
[PATCH v4]: One style nit corrected, also added key to error messages.
[PATCH V3]:All the suggestions in [3] applied. Built on top of [1].
[PATCH V2]: All the suggestions in [2] incorporated. git_config() now follows
correct parsing order. Reordered the patches. Removed xfuncname patch
as it was unnecssary.
This series builds on the top of topic[1] in the mailing list with name
"git config cache & special querying API utilizing the cache" or (ta/config-set in pu).
This series aims to do these three things,
* Use the config-set API to rewrite git_config().
* Solve any legacy bugs in the previous system while at it.
* To be feature complete compared to the previous git_config() implementation,
which I think it is now. (added the line number and file name info just for
completeness)
Also, I haven't yet checked the exact improvements but still as a teaser,
git status now only rereads the configuration files twice instead of four
times.
[1]: http://thread.gmane.org/gmane.comp.version-control.git/254286
[2]: http://thread.gmane.org/gmane.comp.version-control.git/254101
[3]: http://thread.gmane.org/gmane.comp.version-control.git/254211
Matthieu Moy (1):
config.c: mark error and warnings strings for translation
Tanay Abhra (7):
config.c: fix accuracy of line number in errors
add line number and file name info to `config_set`
change `git_config()` return value to void
config: add `git_die_config()` to the config-set API
rewrite git_config() to use the config-set API
add a test for semantic errors in config files
add tests for `git_config_get_string_const()`
Documentation/technical/api-config.txt | 13 +++
branch.c | 5 +-
cache.h | 34 +++++++-
config.c | 152 +++++++++++++++++++++++++++------
t/t1308-config-set.sh | 21 +++++
t/t4055-diff-context.sh | 2 +-
test-config.c | 10 +++
7 files changed, 207 insertions(+), 30 deletions(-)
--
1.9.0.GIT
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v9 1/8] config.c: mark error and warnings strings for translation
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 2/8] config.c: fix accuracy of line number in errors Tanay Abhra
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Matthieu Moy, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
From: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
config.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/config.c b/config.c
index a191328..34940fd 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)
@@ -873,7 +873,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;
}
@@ -1173,7 +1173,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;
@@ -1514,7 +1514,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,
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 2/8] config.c: fix accuracy of line number in errors
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 1/8] config.c: mark error and warnings strings for translation Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 3/8] add line number and file name info to `config_set` Tanay Abhra
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git
Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano,
Matthieu Moy
From: Matthieu Moy <Matthieu.Moy@imag.fr>
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 <tanayabh@gmail.com>
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
config.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/config.c b/config.c
index 34940fd..bb4629e 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)
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 3/8] add line number and file name info to `config_set`
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 1/8] config.c: mark error and warnings strings for translation Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 2/8] config.c: fix accuracy of line number in errors Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 19:33 ` Ramsay Jones
2014-08-07 11:59 ` [PATCH v9 4/8] change `git_config()` return value to void Tanay Abhra
` (5 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
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 <tanayabh@gmail.com>
---
cache.h | 5 +++++
config.c | 16 ++++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/cache.h b/cache.h
index 7292aef..0b1bdfd 100644
--- a/cache.h
+++ b/cache.h
@@ -1383,6 +1383,11 @@ extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
extern int git_config_get_maybe_bool(const char *key, int *dest);
extern int git_config_get_pathname(const char *key, const char **dest);
+struct key_value_info {
+ const char *filename;
+ int linenr;
+};
+
extern int committer_ident_sufficiently_given(void);
extern int author_ident_sufficiently_given(void);
diff --git a/config.c b/config.c
index bb4629e..e4d745e 100644
--- a/config.c
+++ b/config.c
@@ -1260,6 +1260,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
@@ -1272,7 +1275,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;
}
@@ -1299,7 +1311,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;
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 4/8] change `git_config()` return value to void
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (2 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 3/8] add line number and file name info to `config_set` Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 5/8] config: add `git_die_config()` to the config-set API Tanay Abhra
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
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 <Matthieu.Moy@imag.fr>
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
---
branch.c | 5 +----
cache.h | 2 +-
config.c | 16 ++++++++++++++--
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/branch.c b/branch.c
index 46e8aa8..735767d 100644
--- a/branch.c
+++ b/branch.c
@@ -161,10 +161,7 @@ int read_branch_desc(struct strbuf *buf, const char *branch_name)
strbuf_addf(&name, "branch.%s.description", branch_name);
cb.config_name = name.buf;
cb.value = NULL;
- if (git_config(read_branch_desc_cb, &cb) < 0) {
- strbuf_release(&name);
- return -1;
- }
+ git_config(read_branch_desc_cb, &cb);
if (cb.value)
strbuf_addstr(buf, cb.value);
strbuf_release(&name);
diff --git a/cache.h b/cache.h
index 0b1bdfd..f11ce41 100644
--- a/cache.h
+++ b/cache.h
@@ -1294,7 +1294,7 @@ extern int git_config_from_buf(config_fn_t fn, const char *name,
const char *buf, size_t len, void *data);
extern void git_config_push_parameter(const char *text);
extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern int git_config(config_fn_t fn, void *);
+extern void git_config(config_fn_t fn, void *);
extern int git_config_with_options(config_fn_t fn, void *,
struct git_config_source *config_source,
int respect_includes);
diff --git a/config.c b/config.c
index e4d745e..4cefa25 100644
--- a/config.c
+++ b/config.c
@@ -1230,9 +1230,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)
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 5/8] config: add `git_die_config()` to the config-set API
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (3 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 4/8] change `git_config()` return value to void Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 18:55 ` Junio C Hamano
2014-08-07 11:59 ` [PATCH v9 6/8] rewrite git_config() to use " Tanay Abhra
` (3 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
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 <tanayabh@gmail.com>
---
Documentation/technical/api-config.txt | 13 ++++++++++++
cache.h | 3 +++
config.c | 39 ++++++++++++++++++++++++++++++++--
3 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/Documentation/technical/api-config.txt b/Documentation/technical/api-config.txt
index 21f280c..0d8b99b 100644
--- a/Documentation/technical/api-config.txt
+++ b/Documentation/technical/api-config.txt
@@ -155,6 +155,19 @@ as well as retrieval for the queried variable, including:
Similar to `git_config_get_string`, but expands `~` or `~user` into
the user's home directory when found at the beginning of the path.
+`git_die_config(const char *key, const char *err, ...)`::
+
+ First prints the error message specified by the caller in `err` and then
+ dies printing the line number and the file name of the highest priority
+ value for the configuration variable `key`.
+
+`void git_die_config_linenr(const char *key, const char *filename, int linenr)`::
+
+ Helper function which formats the die error message according to the
+ parameters entered. Used by `git_die_config()`. It can be used by callers
+ handling `git_config_get_value_multi()` to print the correct error message
+ for the desired value.
+
See test-config.c for usage examples.
Value Parsing Helpers
diff --git a/cache.h b/cache.h
index f11ce41..89a0d51 100644
--- a/cache.h
+++ b/cache.h
@@ -1388,6 +1388,9 @@ struct key_value_info {
int linenr;
};
+extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
+extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
+
extern int committer_ident_sufficiently_given(void);
extern int author_ident_sufficiently_given(void);
diff --git a/config.c b/config.c
index 4cefa25..5ae9ab0 100644
--- a/config.c
+++ b/config.c
@@ -1469,8 +1469,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)
@@ -1511,8 +1515,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);
}
/*
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 6/8] rewrite git_config() to use the config-set API
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (4 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 5/8] config: add `git_die_config()` to the config-set API Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 7/8] add a test for semantic errors in config files Tanay Abhra
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
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 <tanayabh@gmail.com>
---
cache.h | 24 +++++++++++++++++++++++
config.c | 51 +++++++++++++++++++++++++++++++++++++++++--------
t/t4055-diff-context.sh | 2 +-
3 files changed, 68 insertions(+), 9 deletions(-)
diff --git a/cache.h b/cache.h
index 89a0d51..2693a37 100644
--- a/cache.h
+++ b/cache.h
@@ -8,6 +8,7 @@
#include "gettext.h"
#include "convert.h"
#include "trace.h"
+#include "string-list.h"
#include SHA1_HEADER
#ifndef git_SHA_CTX
@@ -1351,9 +1352,32 @@ extern int parse_config_key(const char *var,
const char **subsection, int *subsection_len,
const char **key);
+struct config_set_element {
+ struct hashmap_entry ent;
+ char *key;
+ struct string_list value_list;
+};
+
+struct configset_list_item {
+ struct config_set_element *e;
+ int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+struct configset_list {
+ struct configset_list_item *items;
+ unsigned int nr, alloc;
+};
+
struct config_set {
struct hashmap config_hash;
int hash_initialized;
+ struct configset_list list;
};
extern void git_configset_init(struct config_set *cs);
diff --git a/config.c b/config.c
index 5ae9ab0..427850a 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;
@@ -1230,7 +1224,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)
/*
@@ -1247,6 +1241,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;
@@ -1273,6 +1294,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);
@@ -1288,6 +1310,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;
@@ -1311,6 +1339,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)
@@ -1327,6 +1358,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)
@@ -1445,7 +1480,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)
diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh
index cd04543..741e080 100755
--- a/t/t4055-diff-context.sh
+++ b/t/t4055-diff-context.sh
@@ -79,7 +79,7 @@ test_expect_success 'non-integer config parsing' '
test_expect_success 'negative integer config parsing' '
git config diff.context -1 &&
test_must_fail git diff 2>output &&
- test_i18ngrep "bad config file" output
+ test_i18ngrep "bad config variable" output
'
test_expect_success '-U0 is valid, so is diff.context=0' '
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 7/8] add a test for semantic errors in config files
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (5 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 6/8] rewrite git_config() to use " Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 8/8] add tests for `git_config_get_string_const()` Tanay Abhra
2014-08-07 12:15 ` [PATCH v9 0/8] Rewrite `git_config()` using config-set API Matthieu Moy
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
Semantic errors (for example, for alias.* variables NULL values are
not allowed) in configuration files cause a die printing the line
number and file name of the offending value.
Add a test documenting that such errors cause a die printing the
accurate line number and file name.
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
---
t/t1308-config-set.sh | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7fdf840..9cc678d 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -197,4 +197,15 @@ test_expect_success 'proper error on error in custom config files' '
test_cmp expect actual
'
+test_expect_success 'check line errors for malformed values' '
+ mv .git/config .git/config.old &&
+ test_when_finished "mv .git/config.old .git/config" &&
+ cat >.git/config <<-\EOF &&
+ [alias]
+ br
+ EOF
+ test_expect_code 128 git br 2>result &&
+ test_i18ngrep "fatal: .*alias\.br.*\.git/config.*line 2" result
+'
+
test_done
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v9 8/8] add tests for `git_config_get_string_const()`
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (6 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 7/8] add a test for semantic errors in config files Tanay Abhra
@ 2014-08-07 11:59 ` Tanay Abhra
2014-08-07 12:15 ` [PATCH v9 0/8] Rewrite `git_config()` using config-set API Matthieu Moy
8 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-07 11:59 UTC (permalink / raw)
To: git; +Cc: Tanay Abhra, Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
Add tests for `git_config_get_string_const()`, check whether it
dies printing the line number and the file name if a NULL
value is retrieved for the given key.
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
---
t/t1308-config-set.sh | 10 ++++++++++
test-config.c | 10 ++++++++++
2 files changed, 20 insertions(+)
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 9cc678d..ea0bce2 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -119,6 +119,16 @@ test_expect_success 'find integer value for a key' '
check_config get_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\""
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+ test_expect_code 128 test-config get_string case.foo 2>result &&
+ test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
+'
+
test_expect_success 'find integer if value is non parse-able' '
check_config expect_code 128 get_int lamb.head
'
diff --git a/test-config.c b/test-config.c
index 9dd1b22..6a77552 100644
--- a/test-config.c
+++ b/test-config.c
@@ -16,6 +16,8 @@
*
* get_bool -> print bool value for the entered key or die
*
+ * get_string -> print string value for the entered key or die
+ *
* configset_get_value -> returns value with the highest priority for the entered key
* from a config_set constructed from files entered as arguments.
*
@@ -84,6 +86,14 @@ int main(int argc, char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
+ } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
+ if (!git_config_get_string_const(argv[2], &v)) {
+ printf("%s\n", v);
+ goto exit0;
+ } else {
+ printf("Value not found for \"%s\"\n", argv[2]);
+ goto exit1;
+ }
} else if (!strcmp(argv[1], "configset_get_value")) {
for (i = 3; i < argc; i++) {
int err;
--
1.9.0.GIT
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v9 0/8] Rewrite `git_config()` using config-set API
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
` (7 preceding siblings ...)
2014-08-07 11:59 ` [PATCH v9 8/8] add tests for `git_config_get_string_const()` Tanay Abhra
@ 2014-08-07 12:15 ` Matthieu Moy
8 siblings, 0 replies; 16+ messages in thread
From: Matthieu Moy @ 2014-08-07 12:15 UTC (permalink / raw)
To: Tanay Abhra; +Cc: git, Ramkumar Ramachandra, Junio C Hamano
Tanay Abhra <tanayabh@gmail.com> writes:
> [Patch v9]: Changed the grep statements in patch 7/8 and 8/8.
Good. I think it adresses all previous comments.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 5/8] config: add `git_die_config()` to the config-set API
2014-08-07 11:59 ` [PATCH v9 5/8] config: add `git_die_config()` to the config-set API Tanay Abhra
@ 2014-08-07 18:55 ` Junio C Hamano
2014-08-08 12:14 ` Tanay Abhra
0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2014-08-07 18:55 UTC (permalink / raw)
To: Tanay Abhra; +Cc: git, Ramkumar Ramachandra, Matthieu Moy
Tanay Abhra <tanayabh@gmail.com> writes:
> diff --git a/Documentation/technical/api-config.txt b/Documentation/technical/api-config.txt
> index 21f280c..0d8b99b 100644
> --- a/Documentation/technical/api-config.txt
> +++ b/Documentation/technical/api-config.txt
> @@ -155,6 +155,19 @@ as well as retrieval for the queried variable, including:
> Similar to `git_config_get_string`, but expands `~` or `~user` into
> the user's home directory when found at the beginning of the path.
>
> +`git_die_config(const char *key, const char *err, ...)`::
> +
> + First prints the error message specified by the caller in `err` and then
> + dies printing the line number and the file name of the highest priority
> + value for the configuration variable `key`.
Reviewed with a wider context, I notice that this entry alone lacks
the return type. I am assuming that this is just an oversight, and
adding 'void ' in front of the filename to match the next entry is
simple enough.
> +`void git_die_config_linenr(const char *key, const char *filename, int linenr)`::
> + ...
> +extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
> ...
> +NORETURN __attribute__((format(printf, 2, 3)))
> +void git_die_config(const char *key, const char *err, ...)
> +{
My first reaction was that it might make the compiler unhappy to
declare that the "err" is a printf-like format string and then to
allow some callers to pass NULL to the function. My build however
does not seem to complain, so perhaps this is OK.
> + 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);
> }
>
> /*
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 3/8] add line number and file name info to `config_set`
2014-08-07 11:59 ` [PATCH v9 3/8] add line number and file name info to `config_set` Tanay Abhra
@ 2014-08-07 19:33 ` Ramsay Jones
2014-08-07 19:56 ` Matthieu Moy
0 siblings, 1 reply; 16+ messages in thread
From: Ramsay Jones @ 2014-08-07 19:33 UTC (permalink / raw)
To: Tanay Abhra, git; +Cc: Ramkumar Ramachandra, Matthieu Moy, Junio C Hamano
On 07/08/14 12:59, Tanay Abhra wrote:
> 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 <tanayabh@gmail.com>
> ---
> cache.h | 5 +++++
> config.c | 16 ++++++++++++++--
> 2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/cache.h b/cache.h
> index 7292aef..0b1bdfd 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1383,6 +1383,11 @@ extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
> extern int git_config_get_maybe_bool(const char *key, int *dest);
> extern int git_config_get_pathname(const char *key, const char **dest);
>
> +struct key_value_info {
> + const char *filename;
> + int linenr;
> +};
> +
I haven't checked, but does this series now include a user for
this struct outside of config.c? If not, then I think it would
be better to leave the declaration in config.c until it is needed.
(To make it easier to see if it is necessary in the context of the
patch which will make use of it).
ATB,
Ramsay Jones
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 3/8] add line number and file name info to `config_set`
2014-08-07 19:33 ` Ramsay Jones
@ 2014-08-07 19:56 ` Matthieu Moy
2014-08-07 20:09 ` Junio C Hamano
0 siblings, 1 reply; 16+ messages in thread
From: Matthieu Moy @ 2014-08-07 19:56 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Tanay Abhra, git, Ramkumar Ramachandra, Junio C Hamano
Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:
> On 07/08/14 12:59, Tanay Abhra wrote:
>> 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 <tanayabh@gmail.com>
>> ---
>> cache.h | 5 +++++
>> config.c | 16 ++++++++++++++--
>> 2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/cache.h b/cache.h
>> index 7292aef..0b1bdfd 100644
>> --- a/cache.h
>> +++ b/cache.h
>> @@ -1383,6 +1383,11 @@ extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
>> extern int git_config_get_maybe_bool(const char *key, int *dest);
>> extern int git_config_get_pathname(const char *key, const char **dest);
>>
>> +struct key_value_info {
>> + const char *filename;
>> + int linenr;
>> +};
>> +
>
> I haven't checked, but does this series now include a user for
> this struct outside of config.c? If not, then I think it would
> be better to leave the declaration in config.c until it is needed.
> (To make it easier to see if it is necessary in the context of the
> patch which will make use of it).
I disagree: this patch series is essentially about introducing a new
API, and this struct declaration is part of the API.
It seemed strange to me to see the code movement in the patch from two
versions of the series, but the patch itself does not move the code, it
just adds new code directly where it belongs.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 3/8] add line number and file name info to `config_set`
2014-08-07 19:56 ` Matthieu Moy
@ 2014-08-07 20:09 ` Junio C Hamano
2014-08-07 20:11 ` Matthieu Moy
0 siblings, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2014-08-07 20:09 UTC (permalink / raw)
To: Matthieu Moy; +Cc: Ramsay Jones, Tanay Abhra, git, Ramkumar Ramachandra
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
> Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:
> ...
>>> diff --git a/cache.h b/cache.h
>>> ...
>>> +struct key_value_info {
>>> + const char *filename;
>>> + int linenr;
>>> +};
>>> +
>>
>> I haven't checked, but does this series now include a user for
>> this struct outside of config.c? If not, then I think it would
>> be better to leave the declaration in config.c until it is needed.
>> (To make it easier to see if it is necessary in the context of the
>> patch which will make use of it).
>
> I disagree: this patch series is essentially about introducing a new
> API, and this struct declaration is part of the API.
Hmm, is it? How would the customer of the API use it? die_config
and friends may internally use the information recorded using the
structure, but I had an impression that it is an implementation
detail that does not need to be exposed to the customers of the API.
Am I mistaken?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 3/8] add line number and file name info to `config_set`
2014-08-07 20:09 ` Junio C Hamano
@ 2014-08-07 20:11 ` Matthieu Moy
0 siblings, 0 replies; 16+ messages in thread
From: Matthieu Moy @ 2014-08-07 20:11 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Ramsay Jones, Tanay Abhra, git, Ramkumar Ramachandra
Junio C Hamano <gitster@pobox.com> writes:
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
>> Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:
>> ...
>>>> diff --git a/cache.h b/cache.h
>>>> ...
>>>> +struct key_value_info {
>>>> + const char *filename;
>>>> + int linenr;
>>>> +};
>>>> +
>>>
>>> I haven't checked, but does this series now include a user for
>>> this struct outside of config.c? If not, then I think it would
>>> be better to leave the declaration in config.c until it is needed.
>>> (To make it easier to see if it is necessary in the context of the
>>> patch which will make use of it).
>>
>> I disagree: this patch series is essentially about introducing a new
>> API, and this struct declaration is part of the API.
>
> Hmm, is it? How would the customer of the API use it? die_config
> and friends may internally use the information recorded using the
> structure, but I had an impression that it is an implementation
> detail that does not need to be exposed to the customers of the API.
> Am I mistaken?
It does if you want to provide error message while iterating over the
string_list. Not the common case, but shouldn't be forbidden either.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v9 5/8] config: add `git_die_config()` to the config-set API
2014-08-07 18:55 ` Junio C Hamano
@ 2014-08-08 12:14 ` Tanay Abhra
0 siblings, 0 replies; 16+ messages in thread
From: Tanay Abhra @ 2014-08-08 12:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ramkumar Ramachandra, Matthieu Moy
On 8/8/2014 12:25 AM, Junio C Hamano wrote:
> Tanay Abhra <tanayabh@gmail.com> writes:
>
>> diff --git a/Documentation/technical/api-config.txt b/Documentation/technical/api-config.txt
>> index 21f280c..0d8b99b 100644
>> --- a/Documentation/technical/api-config.txt
>> +++ b/Documentation/technical/api-config.txt
>> @@ -155,6 +155,19 @@ as well as retrieval for the queried variable, including:
>> Similar to `git_config_get_string`, but expands `~` or `~user` into
>> the user's home directory when found at the beginning of the path.
>>
>> +`git_die_config(const char *key, const char *err, ...)`::
>> +
>> + First prints the error message specified by the caller in `err` and then
>> + dies printing the line number and the file name of the highest priority
>> + value for the configuration variable `key`.
>
> Reviewed with a wider context, I notice that this entry alone lacks
> the return type. I am assuming that this is just an oversight, and
> adding 'void ' in front of the filename to match the next entry is
> simple enough.
>
Yikes, yes, you are right, it's just an oversight. I will send an amended patch.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-08-08 12:15 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-07 11:59 [PATCH v9 0/8] Rewrite `git_config()` using config-set API Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 1/8] config.c: mark error and warnings strings for translation Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 2/8] config.c: fix accuracy of line number in errors Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 3/8] add line number and file name info to `config_set` Tanay Abhra
2014-08-07 19:33 ` Ramsay Jones
2014-08-07 19:56 ` Matthieu Moy
2014-08-07 20:09 ` Junio C Hamano
2014-08-07 20:11 ` Matthieu Moy
2014-08-07 11:59 ` [PATCH v9 4/8] change `git_config()` return value to void Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 5/8] config: add `git_die_config()` to the config-set API Tanay Abhra
2014-08-07 18:55 ` Junio C Hamano
2014-08-08 12:14 ` Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 6/8] rewrite git_config() to use " Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 7/8] add a test for semantic errors in config files Tanay Abhra
2014-08-07 11:59 ` [PATCH v9 8/8] add tests for `git_config_get_string_const()` Tanay Abhra
2014-08-07 12:15 ` [PATCH v9 0/8] Rewrite `git_config()` using config-set API Matthieu Moy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).