From a4e7e317f8f27f861321e6eb08b9c8c0f3ab570c Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:22 +0000 Subject: config: add ctx arg to config_fn_t Add a new "const struct config_context *ctx" arg to config_fn_t to hold additional information about the config iteration operation. config_context has a "struct key_value_info kvi" member that holds metadata about the config source being read (e.g. what kind of config source it is, the filename, etc). In this series, we're only interested in .kvi, so we could have just used "struct key_value_info" as an arg, but config_context makes it possible to add/adjust members in the future without changing the config_fn_t signature. We could also consider other ways of organizing the args (e.g. moving the config name and value into config_context or key_value_info), but in my experiments, the incremental benefit doesn't justify the added complexity (e.g. a config_fn_t will sometimes invoke another config_fn_t but with a different config value). In subsequent commits, the .kvi member will replace the global "struct config_reader" in config.c, making config iteration a global-free operation. It requires much more work for the machinery to provide meaningful values of .kvi, so for now, merely change the signature and call sites, pass NULL as a placeholder value, and don't rely on the arg in any meaningful way. Most of the changes are performed by contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every config_fn_t: - Modifies the signature to accept "const struct config_context *ctx" - Passes "ctx" to any inner config_fn_t, if needed - Adds UNUSED attributes to "ctx", if needed Most config_fn_t instances are easily identified by seeing if they are called by the various config functions. Most of the remaining ones are manually named in the .cocci patch. Manual cleanups are still needed, but the majority of it is trivial; it's either adjusting config_fn_t that the .cocci patch didn't catch, or adding forward declarations of "struct config_context ctx" to make the signatures make sense. The non-trivial changes are in cases where we are invoking a config_fn_t outside of config machinery, and we now need to decide what value of "ctx" to pass. These cases are: - trace2/tr2_cfg.c:tr2_cfg_set_fl() This is indirectly called by git_config_set() so that the trace2 machinery can notice the new config values and update its settings using the tr2 config parsing function, i.e. tr2_cfg_cb(). - builtin/checkout.c:checkout_main() This calls git_xmerge_config() as a shorthand for parsing a CLI arg. This might be worth refactoring away in the future, since git_xmerge_config() can call git_default_config(), which can do much more than just parsing. Handle them by creating a KVI_INIT macro that initializes "struct key_value_info" to a reasonable default, and use that to construct the "ctx" arg. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- config.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 2eeb662142..850e432e30 100644 --- a/config.c +++ b/config.c @@ -209,7 +209,8 @@ struct config_include_data { }; #define CONFIG_INCLUDE_INIT { 0 } -static int git_config_include(const char *var, const char *value, void *data); +static int git_config_include(const char *var, const char *value, + const struct config_context *ctx, void *data); #define MAX_INCLUDE_DEPTH 10 static const char include_depth_advice[] = N_( @@ -388,7 +389,8 @@ static int include_by_branch(const char *cond, size_t cond_len) return ret; } -static int add_remote_url(const char *var, const char *value, void *data) +static int add_remote_url(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *data) { struct string_list *remote_urls = data; const char *remote_name; @@ -423,6 +425,7 @@ static void populate_remote_urls(struct config_include_data *inc) } static int forbid_remote_url(const char *var, const char *value UNUSED, + const struct config_context *ctx UNUSED, void *data UNUSED) { const char *remote_name; @@ -486,7 +489,9 @@ static int include_condition_is_true(struct config_source *cs, return 0; } -static int git_config_include(const char *var, const char *value, void *data) +static int git_config_include(const char *var, const char *value, + const struct config_context *ctx, + void *data) { struct config_include_data *inc = data; struct config_source *cs = inc->config_reader->source; @@ -498,7 +503,7 @@ static int git_config_include(const char *var, const char *value, void *data) * Pass along all values, including "include" directives; this makes it * possible to query information on the includes themselves. */ - ret = inc->fn(var, value, inc->data); + ret = inc->fn(var, value, NULL, inc->data); if (ret < 0) return ret; @@ -680,7 +685,7 @@ static int config_parse_pair(const char *key, const char *value, if (git_config_parse_key(key, &canonical_name, NULL)) return -1; - ret = (fn(canonical_name, value, data) < 0) ? -1 : 0; + ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0; free(canonical_name); return ret; } @@ -968,7 +973,7 @@ static int get_value(struct config_source *cs, config_fn_t fn, void *data, * accurate line number in error messages. */ cs->linenr--; - ret = fn(name->buf, value, data); + ret = fn(name->buf, value, NULL, data); if (ret >= 0) cs->linenr++; return ret; @@ -1562,7 +1567,8 @@ int git_config_color(char *dest, const char *var, const char *value) return 0; } -static int git_default_core_config(const char *var, const char *value, void *cb) +static int git_default_core_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { /* This needs a better name */ if (!strcmp(var, "core.filemode")) { @@ -1842,7 +1848,7 @@ static int git_default_core_config(const char *var, const char *value, void *cb) } /* Add other config variables here and to Documentation/config.txt. */ - return platform_core_config(var, value, cb); + return platform_core_config(var, value, ctx, cb); } static int git_default_sparse_config(const char *var, const char *value) @@ -1944,15 +1950,16 @@ static int git_default_mailmap_config(const char *var, const char *value) return 0; } -int git_default_config(const char *var, const char *value, void *cb) +int git_default_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { if (starts_with(var, "core.")) - return git_default_core_config(var, value, cb); + return git_default_core_config(var, value, ctx, cb); if (starts_with(var, "user.") || starts_with(var, "author.") || starts_with(var, "committer.")) - return git_ident_config(var, value, cb); + return git_ident_config(var, value, ctx, cb); if (starts_with(var, "i18n.")) return git_default_i18n_config(var, value); @@ -2318,7 +2325,7 @@ static void configset_iter(struct config_reader *reader, struct config_set *set, config_reader_set_kvi(reader, values->items[value_index].util); - if (fn(entry->key, values->items[value_index].string, data) < 0) + if (fn(entry->key, values->items[value_index].string, NULL, data) < 0) git_die_config_linenr(entry->key, reader->config_kvi->filename, reader->config_kvi->linenr); @@ -2496,7 +2503,9 @@ struct configset_add_data { }; #define CONFIGSET_ADD_INIT { 0 } -static int config_set_callback(const char *key, const char *value, void *cb) +static int config_set_callback(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *cb) { struct configset_add_data *data = cb; configset_add_value(data->config_reader, data->config_set, key, value); @@ -3106,7 +3115,8 @@ static int store_aux_event(enum config_event_t type, return 0; } -static int store_aux(const char *key, const char *value, void *cb) +static int store_aux(const char *key, const char *value, + const struct config_context *ctx UNUSED, void *cb) { struct config_store_data *store = cb; -- cgit v1.3-5-g9baa From 6021e1d1580169532512772afbb86996f717f4ae Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:23 +0000 Subject: config.c: pass ctx in configsets Pass config_context to config callbacks in configset_iter(), trivially setting the .kvi member to the cached key_value_info. Then, in config callbacks that are only used with configsets, use the .kvi member to replace calls to current_config_*(), and delete current_config_line() because it has no remaining callers. This leaves builtin/config.c and config.c as the only remaining users of current_config_*(). Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- builtin/remote.c | 10 ++++++---- config.c | 35 ++++++++++++++++------------------- config.h | 2 +- remote.c | 7 ++++--- t/helper/test-config.c | 11 ++++++----- 5 files changed, 33 insertions(+), 32 deletions(-) (limited to 'config.c') diff --git a/builtin/remote.c b/builtin/remote.c index 87de81105e..d47f9ee21c 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -646,17 +646,19 @@ struct push_default_info }; static int config_read_push_default(const char *key, const char *value, - const struct config_context *ctx UNUSED, void *cb) + const struct config_context *ctx, void *cb) { + const struct key_value_info *kvi = ctx->kvi; + struct push_default_info* info = cb; if (strcmp(key, "remote.pushdefault") || !value || strcmp(value, info->old_name)) return 0; - info->scope = current_config_scope(); + info->scope = kvi->scope; strbuf_reset(&info->origin); - strbuf_addstr(&info->origin, current_config_name()); - info->linenr = current_config_line(); + strbuf_addstr(&info->origin, config_origin_type_name(kvi->origin_type)); + info->linenr = kvi->linenr; return 0; } diff --git a/config.c b/config.c index 850e432e30..662d406ac1 100644 --- a/config.c +++ b/config.c @@ -2317,6 +2317,7 @@ static void configset_iter(struct config_reader *reader, struct config_set *set, struct string_list *values; struct config_set_element *entry; struct configset_list *list = &set->list; + struct config_context ctx = CONFIG_CONTEXT_INIT; for (i = 0; i < list->nr; i++) { entry = list->items[i].e; @@ -2324,12 +2325,11 @@ static void configset_iter(struct config_reader *reader, struct config_set *set, values = &entry->value_list; config_reader_set_kvi(reader, values->items[value_index].util); - - if (fn(entry->key, values->items[value_index].string, NULL, data) < 0) + ctx.kvi = values->items[value_index].util; + if (fn(entry->key, values->items[value_index].string, &ctx, data) < 0) git_die_config_linenr(entry->key, - reader->config_kvi->filename, - reader->config_kvi->linenr); - + ctx.kvi->filename, + ctx.kvi->linenr); config_reader_set_kvi(reader, NULL); } } @@ -3984,13 +3984,8 @@ static int reader_origin_type(struct config_reader *reader, return 0; } -const char *current_config_origin_type(void) +const char *config_origin_type_name(enum config_origin_type type) { - 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) { case CONFIG_ORIGIN_BLOB: return "blob"; @@ -4007,6 +4002,16 @@ const char *current_config_origin_type(void) } } +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"); + + return config_origin_type_name(type); +} + const char *config_scope_name(enum config_scope scope) { switch (scope) { @@ -4054,14 +4059,6 @@ enum config_scope current_config_scope(void) return the_reader.parsing_scope; } -int current_config_line(void) -{ - if (the_reader.config_kvi) - return the_reader.config_kvi->linenr; - else - return the_reader.source->linenr; -} - int lookup_config(const char **mapping, int nr_mapping, const char *var) { int i; diff --git a/config.h b/config.h index cd30125a8a..ddf147bb2d 100644 --- a/config.h +++ b/config.h @@ -387,7 +387,7 @@ int git_config_parse_parameter(const char *, config_fn_t fn, void *data); enum config_scope current_config_scope(void); const char *current_config_origin_type(void); const char *current_config_name(void); -int current_config_line(void); +const char *config_origin_type_name(enum config_origin_type type); /* * Match and parse a config key of the form: diff --git a/remote.c b/remote.c index 241999c284..1dab860141 100644 --- a/remote.c +++ b/remote.c @@ -350,7 +350,7 @@ static void read_branches_file(struct remote_state *remote_state, } static int handle_config(const char *key, const char *value, - const struct config_context *ctx UNUSED, void *cb) + const struct config_context *ctx, void *cb) { const char *name; size_t namelen; @@ -358,6 +358,7 @@ static int handle_config(const char *key, const char *value, struct remote *remote; struct branch *branch; struct remote_state *remote_state = cb; + const struct key_value_info *kvi = ctx->kvi; if (parse_config_key(key, "branch", &name, &namelen, &subkey) >= 0) { /* There is no subsection. */ @@ -415,8 +416,8 @@ static int handle_config(const char *key, const char *value, } remote = make_remote(remote_state, name, namelen); remote->origin = REMOTE_CONFIG; - if (current_config_scope() == CONFIG_SCOPE_LOCAL || - current_config_scope() == CONFIG_SCOPE_WORKTREE) + if (kvi->scope == CONFIG_SCOPE_LOCAL || + kvi->scope == CONFIG_SCOPE_WORKTREE) remote->configured_in_repo = 1; if (!strcmp(subkey, "mirror")) remote->mirror = git_config_bool(key, value); diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 85ad815358..3f4c367831 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -43,9 +43,10 @@ */ static int iterate_cb(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *data UNUSED) { + const struct key_value_info *kvi = ctx->kvi; static int nr; if (nr++) @@ -53,10 +54,10 @@ static int iterate_cb(const char *var, const char *value, printf("key=%s\n", var); printf("value=%s\n", value ? value : "(null)"); - printf("origin=%s\n", current_config_origin_type()); - printf("name=%s\n", current_config_name()); - printf("lno=%d\n", current_config_line()); - printf("scope=%s\n", config_scope_name(current_config_scope())); + printf("origin=%s\n", config_origin_type_name(kvi->origin_type)); + printf("name=%s\n", kvi->filename ? kvi->filename : ""); + printf("lno=%d\n", kvi->linenr); + printf("scope=%s\n", config_scope_name(kvi->scope)); return 0; } -- cgit v1.3-5-g9baa From 809d868061c5e55e9b3bd59a4118628318eb46e9 Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:24 +0000 Subject: config: pass ctx with config files Pass config_context to config_callbacks when parsing config files. To provide the .kvi member, refactor out the configset logic that caches "struct config_source" and "enum config_scope" as a "struct key_value_info". Make the "enum config_scope" available to the config file machinery by plumbing an additional arg through git_config_from_file_with_options(). We do not exercise ctx yet because the remaining current_config_*() callers may be used with config_with_options(), which may read config from parameters, but parameters don't pass ctx yet. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- bundle-uri.c | 1 + config.c | 105 +++++++++++++++++++++++++++++++++++------------------ config.h | 8 ++-- fsck.c | 3 +- submodule-config.c | 5 ++- 5 files changed, 81 insertions(+), 41 deletions(-) (limited to 'config.c') diff --git a/bundle-uri.c b/bundle-uri.c index 0d5acc3dc5..64f3238774 100644 --- a/bundle-uri.c +++ b/bundle-uri.c @@ -255,6 +255,7 @@ int bundle_uri_parse_config_format(const char *uri, } result = git_config_from_file_with_options(config_to_bundle_list, filename, list, + CONFIG_SCOPE_UNKNOWN, &opts); if (!result && list->mode == BUNDLE_MODE_NONE) { diff --git a/config.c b/config.c index 662d406ac1..3171871182 100644 --- a/config.c +++ b/config.c @@ -259,7 +259,9 @@ static int handle_path_include(struct config_source *cs, const char *path, !cs ? "" : cs->name ? cs->name : "the command line"); - ret = git_config_from_file(git_config_include, path, inc); + ret = git_config_from_file_with_options(git_config_include, path, inc, + current_config_scope(), + NULL); inc->depth--; } cleanup: @@ -503,7 +505,7 @@ static int git_config_include(const char *var, const char *value, * Pass along all values, including "include" directives; this makes it * possible to query information on the includes themselves. */ - ret = inc->fn(var, value, NULL, inc->data); + ret = inc->fn(var, value, ctx, inc->data); if (ret < 0) return ret; @@ -939,12 +941,15 @@ static char *parse_value(struct config_source *cs) } } -static int get_value(struct config_source *cs, config_fn_t fn, void *data, - struct strbuf *name) +static int get_value(struct config_source *cs, struct key_value_info *kvi, + config_fn_t fn, void *data, struct strbuf *name) { int c; char *value; int ret; + struct config_context ctx = { + .kvi = kvi, + }; /* Get the full name */ for (;;) { @@ -973,7 +978,8 @@ static int get_value(struct config_source *cs, config_fn_t fn, void *data, * accurate line number in error messages. */ cs->linenr--; - ret = fn(name->buf, value, NULL, data); + kvi->linenr = cs->linenr; + ret = fn(name->buf, value, &ctx, data); if (ret >= 0) cs->linenr++; return ret; @@ -1072,8 +1078,19 @@ static int do_event(struct config_source *cs, enum config_event_t type, return 0; } +static void kvi_from_source(struct config_source *cs, + enum config_scope scope, + struct key_value_info *out) +{ + out->filename = strintern(cs->name); + out->origin_type = cs->origin_type; + out->linenr = cs->linenr; + out->scope = scope; +} + static int git_parse_source(struct config_source *cs, config_fn_t fn, - void *data, const struct config_options *opts) + struct key_value_info *kvi, void *data, + const struct config_options *opts) { int comment = 0; size_t baselen = 0; @@ -1157,7 +1174,7 @@ static int git_parse_source(struct config_source *cs, config_fn_t fn, */ strbuf_setlen(var, baselen); strbuf_addch(var, tolower(c)); - if (get_value(cs, fn, data, var) < 0) + if (get_value(cs, kvi, fn, data, var) < 0) break; } @@ -2010,9 +2027,11 @@ int git_default_config(const char *var, const char *value, * this function. */ static int do_config_from(struct config_reader *reader, - struct config_source *top, config_fn_t fn, void *data, + struct config_source *top, config_fn_t fn, + void *data, enum config_scope scope, const struct config_options *opts) { + struct key_value_info kvi = KVI_INIT; int ret; /* push config-file parsing state stack */ @@ -2022,8 +2041,9 @@ static int do_config_from(struct config_reader *reader, strbuf_init(&top->value, 1024); strbuf_init(&top->var, 1024); config_reader_push_source(reader, top); + kvi_from_source(top, scope, &kvi); - ret = git_parse_source(top, fn, data, opts); + ret = git_parse_source(top, fn, &kvi, data, opts); /* pop config-file parsing state stack */ strbuf_release(&top->value); @@ -2037,7 +2057,8 @@ static int do_config_from_file(struct config_reader *reader, config_fn_t fn, const enum config_origin_type origin_type, const char *name, const char *path, FILE *f, - void *data, const struct config_options *opts) + void *data, enum config_scope scope, + const struct config_options *opts) { struct config_source top = CONFIG_SOURCE_INIT; int ret; @@ -2052,19 +2073,20 @@ static int do_config_from_file(struct config_reader *reader, top.do_ftell = config_file_ftell; flockfile(f); - ret = do_config_from(reader, &top, fn, data, opts); + ret = do_config_from(reader, &top, fn, data, scope, opts); funlockfile(f); return ret; } -static int git_config_from_stdin(config_fn_t fn, void *data) +static int git_config_from_stdin(config_fn_t fn, void *data, + enum config_scope scope) { return do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_STDIN, "", - NULL, stdin, data, NULL); + NULL, stdin, data, scope, NULL); } int git_config_from_file_with_options(config_fn_t fn, const char *filename, - void *data, + void *data, enum config_scope scope, const struct config_options *opts) { int ret = -1; @@ -2075,7 +2097,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename, f = fopen_or_warn(filename, "r"); if (f) { ret = do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_FILE, - filename, filename, f, data, opts); + filename, filename, f, data, scope, + opts); fclose(f); } return ret; @@ -2083,13 +2106,15 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename, int git_config_from_file(config_fn_t fn, const char *filename, void *data) { - return git_config_from_file_with_options(fn, filename, data, NULL); + return git_config_from_file_with_options(fn, filename, data, + CONFIG_SCOPE_UNKNOWN, NULL); } int git_config_from_mem(config_fn_t fn, const enum config_origin_type origin_type, const char *name, const char *buf, size_t len, - void *data, const struct config_options *opts) + void *data, enum config_scope scope, + const struct config_options *opts) { struct config_source top = CONFIG_SOURCE_INIT; @@ -2104,14 +2129,15 @@ int git_config_from_mem(config_fn_t fn, top.do_ungetc = config_buf_ungetc; top.do_ftell = config_buf_ftell; - return do_config_from(&the_reader, &top, fn, data, opts); + return do_config_from(&the_reader, &top, fn, data, scope, opts); } int git_config_from_blob_oid(config_fn_t fn, const char *name, struct repository *repo, const struct object_id *oid, - void *data) + void *data, + enum config_scope scope) { enum object_type type; char *buf; @@ -2127,7 +2153,7 @@ int git_config_from_blob_oid(config_fn_t fn, } ret = git_config_from_mem(fn, CONFIG_ORIGIN_BLOB, name, buf, size, - data, NULL); + data, scope, NULL); free(buf); return ret; @@ -2136,13 +2162,14 @@ int git_config_from_blob_oid(config_fn_t fn, static int git_config_from_blob_ref(config_fn_t fn, struct repository *repo, const char *name, - void *data) + void *data, + enum config_scope scope) { struct object_id oid; if (repo_get_oid(repo, name, &oid) < 0) return error(_("unable to resolve config blob '%s'"), name); - return git_config_from_blob_oid(fn, name, repo, &oid, data); + return git_config_from_blob_oid(fn, name, repo, &oid, data, scope); } char *git_system_config(void) @@ -2228,27 +2255,34 @@ static int do_git_config_sequence(struct config_reader *reader, if (git_config_system() && system_config && !access_or_die(system_config, R_OK, opts->system_gently ? ACCESS_EACCES_OK : 0)) - ret += git_config_from_file(fn, system_config, data); + ret += git_config_from_file_with_options(fn, system_config, + data, CONFIG_SCOPE_SYSTEM, + NULL); config_reader_set_scope(reader, CONFIG_SCOPE_GLOBAL); git_global_config(&user_config, &xdg_config); if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) - ret += git_config_from_file(fn, xdg_config, data); + ret += git_config_from_file_with_options(fn, xdg_config, data, + CONFIG_SCOPE_GLOBAL, NULL); if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) - ret += git_config_from_file(fn, user_config, data); + ret += git_config_from_file_with_options(fn, user_config, data, + CONFIG_SCOPE_GLOBAL, NULL); config_reader_set_scope(reader, CONFIG_SCOPE_LOCAL); if (!opts->ignore_repo && repo_config && !access_or_die(repo_config, R_OK, 0)) - ret += git_config_from_file(fn, repo_config, data); + ret += git_config_from_file_with_options(fn, repo_config, data, + CONFIG_SCOPE_LOCAL, NULL); config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE); if (!opts->ignore_worktree && worktree_config && repo && repo->repository_format_worktree_config && !access_or_die(worktree_config, R_OK, 0)) { - ret += git_config_from_file(fn, worktree_config, data); + ret += git_config_from_file_with_options(fn, worktree_config, data, + CONFIG_SCOPE_WORKTREE, + NULL); } config_reader_set_scope(reader, CONFIG_SCOPE_COMMAND); @@ -2292,12 +2326,14 @@ int config_with_options(config_fn_t fn, void *data, * regular lookup sequence. */ if (config_source && config_source->use_stdin) { - ret = git_config_from_stdin(fn, data); + ret = git_config_from_stdin(fn, data, config_source->scope); } else if (config_source && config_source->file) { - ret = git_config_from_file(fn, config_source->file, data); + ret = git_config_from_file_with_options(fn, config_source->file, + data, config_source->scope, + NULL); } else if (config_source && config_source->blob) { ret = git_config_from_blob_ref(fn, repo, config_source->blob, - data); + data, config_source->scope); } else { ret = do_git_config_sequence(&the_reader, opts, repo, fn, data); } @@ -2440,16 +2476,14 @@ static int configset_add_value(struct config_reader *reader, if (!reader->source) BUG("configset_add_value has no source"); if (reader->source->name) { - kv_info->filename = strintern(reader->source->name); - kv_info->linenr = reader->source->linenr; - kv_info->origin_type = reader->source->origin_type; + kvi_from_source(reader->source, current_config_scope(), kv_info); } else { /* for values read from `git_config_from_parameters()` */ kv_info->filename = NULL; kv_info->linenr = -1; kv_info->origin_type = CONFIG_ORIGIN_CMDLINE; + kv_info->scope = reader->parsing_scope; } - kv_info->scope = reader->parsing_scope; si->util = kv_info; return 0; @@ -3490,7 +3524,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, */ if (git_config_from_file_with_options(store_aux, config_filename, - &store, &opts)) { + &store, CONFIG_SCOPE_UNKNOWN, + &opts)) { error(_("invalid config file %s"), config_filename); ret = CONFIG_INVALID_FILE; goto out_free; diff --git a/config.h b/config.h index ddf147bb2d..206bf1f175 100644 --- a/config.h +++ b/config.h @@ -169,16 +169,18 @@ int git_default_config(const char *, const char *, int git_config_from_file(config_fn_t fn, const char *, void *); int git_config_from_file_with_options(config_fn_t fn, const char *, - void *, + void *, enum config_scope, const struct config_options *); int git_config_from_mem(config_fn_t fn, const enum config_origin_type, const char *name, const char *buf, size_t len, - void *data, const struct config_options *opts); + void *data, enum config_scope scope, + const struct config_options *opts); int git_config_from_blob_oid(config_fn_t fn, const char *name, struct repository *repo, - const struct object_id *oid, void *data); + const struct object_id *oid, void *data, + enum config_scope scope); void git_config_push_parameter(const char *text); void git_config_push_env(const char *spec); int git_config_from_parameters(config_fn_t fn, void *data); diff --git a/fsck.c b/fsck.c index 55b6a69485..f92c216fb5 100644 --- a/fsck.c +++ b/fsck.c @@ -1238,7 +1238,8 @@ static int fsck_blob(const struct object_id *oid, const char *buf, data.ret = 0; config_opts.error_action = CONFIG_ERROR_SILENT; if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB, - ".gitmodules", buf, size, &data, &config_opts)) + ".gitmodules", buf, size, &data, + CONFIG_SCOPE_UNKNOWN, &config_opts)) data.ret |= report(options, oid, OBJ_BLOB, FSCK_MSG_GITMODULES_PARSE, "could not parse gitmodules blob"); diff --git a/submodule-config.c b/submodule-config.c index a38d4d4973..3f25bd1367 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -606,7 +606,7 @@ static const struct submodule *config_from(struct submodule_cache *cache, parameter.gitmodules_oid = &oid; parameter.overwrite = 0; git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf, - config, config_size, ¶meter, NULL); + config, config_size, ¶meter, CONFIG_SCOPE_UNKNOWN, NULL); strbuf_release(&rev); free(config); @@ -714,7 +714,8 @@ void gitmodules_config_oid(const struct object_id *commit_oid) if (gitmodule_oid_from_commit(commit_oid, &oid, &rev)) { git_config_from_blob_oid(gitmodules_cb, rev.buf, - the_repository, &oid, the_repository); + the_repository, &oid, the_repository, + CONFIG_SCOPE_UNKNOWN); } strbuf_release(&rev); -- cgit v1.3-5-g9baa From 26b669324bb3ef8fd15387815bc020f08d0b4e7b Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:25 +0000 Subject: config.c: pass ctx with CLI config Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/ Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- builtin/config.c | 47 ++++++++++++++++++++------------ config.c | 80 ++++++++++++++++++++++++++++--------------------------- config.h | 3 +-- t/t1300-config.sh | 27 +++++++++++++++++++ 4 files changed, 99 insertions(+), 58 deletions(-) (limited to 'config.c') diff --git a/builtin/config.c b/builtin/config.c index f4fccf99cb..9b9f552731 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -194,38 +194,42 @@ static void check_argc(int argc, int min, int max) usage_builtin_config(); } -static void show_config_origin(struct strbuf *buf) +static void show_config_origin(const struct key_value_info *kvi, + struct strbuf *buf) { const char term = end_nul ? '\0' : '\t'; - strbuf_addstr(buf, current_config_origin_type()); + strbuf_addstr(buf, config_origin_type_name(kvi->origin_type)); strbuf_addch(buf, ':'); if (end_nul) - strbuf_addstr(buf, current_config_name()); + strbuf_addstr(buf, kvi->filename ? kvi->filename : ""); else - quote_c_style(current_config_name(), buf, NULL, 0); + quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0); strbuf_addch(buf, term); } -static void show_config_scope(struct strbuf *buf) +static void show_config_scope(const struct key_value_info *kvi, + struct strbuf *buf) { const char term = end_nul ? '\0' : '\t'; - const char *scope = config_scope_name(current_config_scope()); + const char *scope = config_scope_name(kvi->scope); strbuf_addstr(buf, N_(scope)); strbuf_addch(buf, term); } static int show_all_config(const char *key_, const char *value_, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb UNUSED) { + const struct key_value_info *kvi = ctx->kvi; + if (show_origin || show_scope) { struct strbuf buf = STRBUF_INIT; if (show_scope) - show_config_scope(&buf); + show_config_scope(kvi, &buf); if (show_origin) - show_config_origin(&buf); + show_config_origin(kvi, &buf); /* Use fwrite as "buf" can contain \0's if "end_null" is set. */ fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf); @@ -243,12 +247,13 @@ struct strbuf_list { int alloc; }; -static int format_config(struct strbuf *buf, const char *key_, const char *value_) +static int format_config(struct strbuf *buf, const char *key_, + const char *value_, const struct key_value_info *kvi) { if (show_scope) - show_config_scope(buf); + show_config_scope(kvi, buf); if (show_origin) - show_config_origin(buf); + show_config_origin(kvi, buf); if (show_keys) strbuf_addstr(buf, key_); if (!omit_values) { @@ -303,9 +308,10 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value } static int collect_config(const char *key_, const char *value_, - const struct config_context *ctx UNUSED, void *cb) + const struct config_context *ctx, void *cb) { struct strbuf_list *values = cb; + const struct key_value_info *kvi = ctx->kvi; if (!use_key_regexp && strcmp(key_, key)) return 0; @@ -320,7 +326,7 @@ static int collect_config(const char *key_, const char *value_, ALLOC_GROW(values->items, values->nr + 1, values->alloc); strbuf_init(&values->items[values->nr], 0); - return format_config(&values->items[values->nr++], key_, value_); + return format_config(&values->items[values->nr++], key_, value_, kvi); } static int get_value(const char *key_, const char *regex_, unsigned flags) @@ -382,11 +388,14 @@ static int get_value(const char *key_, const char *regex_, unsigned flags) &config_options); if (!values.nr && default_value) { + struct key_value_info kvi = KVI_INIT; struct strbuf *item; + + kvi_from_param(&kvi); ALLOC_GROW(values.items, values.nr + 1, values.alloc); item = &values.items[values.nr++]; strbuf_init(item, 0); - if (format_config(item, key_, default_value) < 0) + if (format_config(item, key_, default_value, &kvi) < 0) die(_("failed to format default config value: %s"), default_value); } @@ -563,15 +572,17 @@ static void check_write(void) struct urlmatch_current_candidate_value { char value_is_null; struct strbuf value; + struct key_value_info kvi; }; static int urlmatch_collect_fn(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb) { struct string_list *values = cb; struct string_list_item *item = string_list_insert(values, var); struct urlmatch_current_candidate_value *matched = item->util; + const struct key_value_info *kvi = ctx->kvi; if (!matched) { matched = xmalloc(sizeof(*matched)); @@ -580,6 +591,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, } else { strbuf_reset(&matched->value); } + matched->kvi = *kvi; if (value) { strbuf_addstr(&matched->value, value); @@ -627,7 +639,8 @@ static int get_urlmatch(const char *var, const char *url) struct strbuf buf = STRBUF_INIT; format_config(&buf, item->string, - matched->value_is_null ? NULL : matched->value.buf); + matched->value_is_null ? NULL : matched->value.buf, + &matched->kvi); fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf); diff --git a/config.c b/config.c index 3171871182..4986942b09 100644 --- a/config.c +++ b/config.c @@ -219,7 +219,9 @@ static const char include_depth_advice[] = N_( "from\n" " %s\n" "This might be due to circular includes."); -static int handle_path_include(struct config_source *cs, const char *path, +static int handle_path_include(struct config_source *cs, + const struct key_value_info *kvi, + const char *path, struct config_include_data *inc) { int ret = 0; @@ -260,8 +262,7 @@ static int handle_path_include(struct config_source *cs, const char *path, cs->name ? cs->name : "the command line"); ret = git_config_from_file_with_options(git_config_include, path, inc, - current_config_scope(), - NULL); + kvi->scope, NULL); inc->depth--; } cleanup: @@ -510,7 +511,7 @@ static int git_config_include(const char *var, const char *value, return ret; if (!strcmp(var, "include.path")) - ret = handle_path_include(cs, value, inc); + ret = handle_path_include(cs, ctx->kvi, value, inc); if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) && cond && include_condition_is_true(cs, inc, cond, cond_len) && @@ -519,7 +520,7 @@ static int git_config_include(const char *var, const char *value, if (inc->opts->unconditional_remote_url) inc->fn = forbid_remote_url; - ret = handle_path_include(cs, value, inc); + ret = handle_path_include(cs, ctx->kvi, value, inc); inc->fn = old_fn; } @@ -677,27 +678,44 @@ out_free_ret_1: } static int config_parse_pair(const char *key, const char *value, - config_fn_t fn, void *data) + struct key_value_info *kvi, + config_fn_t fn, void *data) { char *canonical_name; int ret; + struct config_context ctx = { + .kvi = kvi, + }; if (!strlen(key)) return error(_("empty config key")); if (git_config_parse_key(key, &canonical_name, NULL)) return -1; - ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0; + ret = (fn(canonical_name, value, &ctx, data) < 0) ? -1 : 0; free(canonical_name); return ret; } + +/* for values read from `git_config_from_parameters()` */ +void kvi_from_param(struct key_value_info *out) +{ + out->filename = NULL; + out->linenr = -1; + out->origin_type = CONFIG_ORIGIN_CMDLINE; + out->scope = CONFIG_SCOPE_COMMAND; +} + int git_config_parse_parameter(const char *text, config_fn_t fn, void *data) { const char *value; struct strbuf **pair; int ret; + struct key_value_info kvi = KVI_INIT; + + kvi_from_param(&kvi); pair = strbuf_split_str(text, '=', 2); if (!pair[0]) @@ -716,12 +734,13 @@ int git_config_parse_parameter(const char *text, return error(_("bogus config parameter: %s"), text); } - ret = config_parse_pair(pair[0]->buf, value, fn, data); + ret = config_parse_pair(pair[0]->buf, value, &kvi, fn, data); strbuf_list_free(pair); return ret; } -static int parse_config_env_list(char *env, config_fn_t fn, void *data) +static int parse_config_env_list(char *env, struct key_value_info *kvi, + config_fn_t fn, void *data) { char *cur = env; while (cur && *cur) { @@ -755,7 +774,7 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data) CONFIG_DATA_ENVIRONMENT); } - if (config_parse_pair(key, value, fn, data) < 0) + if (config_parse_pair(key, value, kvi, fn, data) < 0) return -1; } else { @@ -780,10 +799,13 @@ int git_config_from_parameters(config_fn_t fn, void *data) int ret = 0; char *envw = NULL; struct config_source source = CONFIG_SOURCE_INIT; + struct key_value_info kvi = KVI_INIT; source.origin_type = CONFIG_ORIGIN_CMDLINE; config_reader_push_source(&the_reader, &source); + kvi_from_param(&kvi); + env = getenv(CONFIG_COUNT_ENVIRONMENT); if (env) { unsigned long count; @@ -819,7 +841,7 @@ int git_config_from_parameters(config_fn_t fn, void *data) } strbuf_reset(&envvar); - if (config_parse_pair(key, value, fn, data) < 0) { + if (config_parse_pair(key, value, &kvi, fn, data) < 0) { ret = -1; goto out; } @@ -830,7 +852,7 @@ int git_config_from_parameters(config_fn_t fn, void *data) if (env) { /* sq_dequote will write over it */ envw = xstrdup(env); - if (parse_config_env_list(envw, fn, data) < 0) { + if (parse_config_env_list(envw, &kvi, fn, data) < 0) { ret = -1; goto out; } @@ -2442,7 +2464,8 @@ static int configset_find_element(struct config_set *set, const char *key, return 0; } -static int configset_add_value(struct config_reader *reader, +static int configset_add_value(const struct key_value_info *kvi_p, + struct config_reader *reader, struct config_set *set, const char *key, const char *value) { @@ -2476,13 +2499,9 @@ static int configset_add_value(struct config_reader *reader, if (!reader->source) BUG("configset_add_value has no source"); if (reader->source->name) { - kvi_from_source(reader->source, current_config_scope(), kv_info); + kvi_from_source(reader->source, kvi_p->scope, kv_info); } else { - /* for values read from `git_config_from_parameters()` */ - kv_info->filename = NULL; - kv_info->linenr = -1; - kv_info->origin_type = CONFIG_ORIGIN_CMDLINE; - kv_info->scope = reader->parsing_scope; + kvi_from_param(kv_info); } si->util = kv_info; @@ -2538,11 +2557,12 @@ struct configset_add_data { #define CONFIGSET_ADD_INIT { 0 } static int config_set_callback(const char *key, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb) { struct configset_add_data *data = cb; - configset_add_value(data->config_reader, data->config_set, key, value); + configset_add_value(ctx->kvi, data->config_reader, data->config_set, + key, value); return 0; } @@ -4037,16 +4057,6 @@ const char *config_origin_type_name(enum config_origin_type type) } } -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"); - - return config_origin_type_name(type); -} - const char *config_scope_name(enum config_scope scope) { switch (scope) { @@ -4078,14 +4088,6 @@ static int reader_config_name(struct config_reader *reader, const char **out) 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 : ""; -} - enum config_scope current_config_scope(void) { if (the_reader.config_kvi) diff --git a/config.h b/config.h index 206bf1f175..ea92392400 100644 --- a/config.h +++ b/config.h @@ -387,9 +387,8 @@ void git_global_config(char **user, char **xdg); int git_config_parse_parameter(const char *, config_fn_t fn, void *data); enum config_scope current_config_scope(void); -const char *current_config_origin_type(void); -const char *current_config_name(void); const char *config_origin_type_name(enum config_origin_type type); +void kvi_from_param(struct key_value_info *out); /* * Match and parse a config key of the form: diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 86bfbc2b36..387d336c91 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1668,6 +1668,21 @@ test_expect_success 'urlmatch' ' test_cmp expect actual ' +test_expect_success 'urlmatch with --show-scope' ' + cat >.git/config <<-\EOF && + [http "https://weak.example.com"] + sslVerify = false + cookieFile = /tmp/cookie.txt + EOF + + cat >expect <<-EOF && + local http.cookiefile /tmp/cookie.txt + local http.sslverify false + EOF + git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual && + test_cmp expect actual +' + test_expect_success 'urlmatch favors more specific URLs' ' cat >.git/config <<-\EOF && [http "https://example.com/"] @@ -2055,6 +2070,12 @@ test_expect_success '--show-origin blob ref' ' test_cmp expect output ' +test_expect_success '--show-origin with --default' ' + git config --show-origin --default foo some.key >actual && + echo "command line: foo" >expect && + test_cmp expect actual +' + test_expect_success '--show-scope with --list' ' cat >expect <<-EOF && global user.global=true @@ -2123,6 +2144,12 @@ test_expect_success '--show-scope with --show-origin' ' test_cmp expect output ' +test_expect_success '--show-scope with --default' ' + git config --show-scope --default foo some.key >actual && + echo "command foo" >expect && + test_cmp expect actual +' + test_expect_success 'override global and system config' ' test_when_finished rm -f \"\$HOME\"/.gitconfig && cat >"$HOME"/.gitconfig <<-EOF && -- cgit v1.3-5-g9baa From dc9020849773393e47c37c2834a5582374b55ecc Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:26 +0000 Subject: trace2: plumb config kvi There is a code path starting from trace2_def_param_fl() that eventually calls current_config_scope(), and thus it needs to have "kvi" plumbed through it. Additional plumbing is also needed to get "kvi" to trace2_def_param_fl(), which gets called by two code paths: - Through tr2_cfg_cb(), which is a config callback, so it trivially receives "kvi" via the "struct config_context ctx" parameter. - Through tr2_list_env_vars_fl(), which is a high level function that lists environment variables for tracing. This has been secretly behaving like git_config_from_parameters() (in that it parses config from environment variables/the CLI), but does not set config source information. Teach tr2_list_env_vars_fl() to be well-behaved by using kvi_from_param(), which is used elsewhere for CLI/environment variable-based config. As a result, current_config_scope() has no more callers, so remove it. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- config.c | 46 ---------------------------------------------- config.h | 1 - trace2.c | 4 ++-- trace2.h | 3 ++- trace2/tr2_cfg.c | 9 ++++++--- trace2/tr2_tgt.h | 4 +++- trace2/tr2_tgt_event.c | 4 ++-- trace2/tr2_tgt_normal.c | 4 ++-- trace2/tr2_tgt_perf.c | 4 ++-- 9 files changed, 19 insertions(+), 60 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 4986942b09..d10faba56d 100644 --- a/config.c +++ b/config.c @@ -85,16 +85,6 @@ struct config_reader { */ struct config_source *source; struct key_value_info *config_kvi; - /* - * The "scope" of the current config source being parsed (repo, global, - * etc). Like "source", this is only set when parsing a config source. - * It's not part of "source" because it transcends a single file (i.e., - * a file included from .git/config is still in "repo" scope). - * - * When iterating through a configset, the equivalent value is - * "config_kvi.scope" (see above). - */ - enum config_scope parsing_scope; }; /* * Where possible, prefer to accept "struct config_reader" as an arg than to use @@ -125,19 +115,9 @@ static inline struct config_source *config_reader_pop_source(struct config_reade static inline void config_reader_set_kvi(struct config_reader *reader, struct key_value_info *kvi) { - if (kvi && (reader->source || reader->parsing_scope)) - BUG("kvi should not be set while parsing a config source"); reader->config_kvi = kvi; } -static inline void config_reader_set_scope(struct config_reader *reader, - enum config_scope scope) -{ - if (scope && reader->config_kvi) - BUG("scope should only be set when iterating through a config source"); - reader->parsing_scope = scope; -} - static int pack_compression_seen; static int zlib_compression_seen; @@ -412,19 +392,13 @@ static void populate_remote_urls(struct config_include_data *inc) { struct config_options opts; - enum config_scope store_scope = inc->config_reader->parsing_scope; - opts = *inc->opts; opts.unconditional_remote_url = 1; - config_reader_set_scope(inc->config_reader, 0); - inc->remote_urls = xmalloc(sizeof(*inc->remote_urls)); string_list_init_dup(inc->remote_urls); config_with_options(add_remote_url, inc->remote_urls, inc->config_source, inc->repo, &opts); - - config_reader_set_scope(inc->config_reader, store_scope); } static int forbid_remote_url(const char *var, const char *value UNUSED, @@ -2255,7 +2229,6 @@ static int do_git_config_sequence(struct config_reader *reader, char *user_config = NULL; char *repo_config; char *worktree_config; - enum config_scope prev_parsing_scope = reader->parsing_scope; /* * Ensure that either: @@ -2273,7 +2246,6 @@ static int do_git_config_sequence(struct config_reader *reader, worktree_config = NULL; } - config_reader_set_scope(reader, CONFIG_SCOPE_SYSTEM); if (git_config_system() && system_config && !access_or_die(system_config, R_OK, opts->system_gently ? ACCESS_EACCES_OK : 0)) @@ -2281,7 +2253,6 @@ static int do_git_config_sequence(struct config_reader *reader, data, CONFIG_SCOPE_SYSTEM, NULL); - config_reader_set_scope(reader, CONFIG_SCOPE_GLOBAL); git_global_config(&user_config, &xdg_config); if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) @@ -2292,13 +2263,11 @@ static int do_git_config_sequence(struct config_reader *reader, ret += git_config_from_file_with_options(fn, user_config, data, CONFIG_SCOPE_GLOBAL, NULL); - config_reader_set_scope(reader, CONFIG_SCOPE_LOCAL); if (!opts->ignore_repo && repo_config && !access_or_die(repo_config, R_OK, 0)) ret += git_config_from_file_with_options(fn, repo_config, data, CONFIG_SCOPE_LOCAL, NULL); - config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE); if (!opts->ignore_worktree && worktree_config && repo && repo->repository_format_worktree_config && !access_or_die(worktree_config, R_OK, 0)) { @@ -2307,11 +2276,9 @@ static int do_git_config_sequence(struct config_reader *reader, NULL); } - config_reader_set_scope(reader, CONFIG_SCOPE_COMMAND); if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0) die(_("unable to parse command-line config")); - config_reader_set_scope(reader, prev_parsing_scope); free(system_config); free(xdg_config); free(user_config); @@ -2326,7 +2293,6 @@ int config_with_options(config_fn_t fn, void *data, const struct config_options *opts) { struct config_include_data inc = CONFIG_INCLUDE_INIT; - enum config_scope prev_scope = the_reader.parsing_scope; int ret; if (opts->respect_includes) { @@ -2340,9 +2306,6 @@ int config_with_options(config_fn_t fn, void *data, data = &inc; } - if (config_source) - config_reader_set_scope(&the_reader, config_source->scope); - /* * If we have a specific filename, use it. Otherwise, follow the * regular lookup sequence. @@ -2364,7 +2327,6 @@ int config_with_options(config_fn_t fn, void *data, string_list_clear(inc.remote_urls, 0); FREE_AND_NULL(inc.remote_urls); } - config_reader_set_scope(&the_reader, prev_scope); return ret; } @@ -4088,14 +4050,6 @@ static int reader_config_name(struct config_reader *reader, const char **out) return 0; } -enum config_scope current_config_scope(void) -{ - if (the_reader.config_kvi) - return the_reader.config_kvi->scope; - else - return the_reader.parsing_scope; -} - int lookup_config(const char **mapping, int nr_mapping, const char *var) { int i; diff --git a/config.h b/config.h index ea92392400..82eeba94e7 100644 --- a/config.h +++ b/config.h @@ -386,7 +386,6 @@ void git_global_config(char **user, char **xdg); int git_config_parse_parameter(const char *, config_fn_t fn, void *data); -enum config_scope current_config_scope(void); const char *config_origin_type_name(enum config_origin_type type); void kvi_from_param(struct key_value_info *out); diff --git a/trace2.c b/trace2.c index 0efc4e7b95..49c23bfd05 100644 --- a/trace2.c +++ b/trace2.c @@ -634,7 +634,7 @@ void trace2_thread_exit_fl(const char *file, int line) } void trace2_def_param_fl(const char *file, int line, const char *param, - const char *value) + const char *value, const struct key_value_info *kvi) { struct tr2_tgt *tgt_j; int j; @@ -644,7 +644,7 @@ void trace2_def_param_fl(const char *file, int line, const char *param, for_each_wanted_builtin (j, tgt_j) if (tgt_j->pfn_param_fl) - tgt_j->pfn_param_fl(file, line, param, value); + tgt_j->pfn_param_fl(file, line, param, value, kvi); } void trace2_def_repo_fl(const char *file, int line, struct repository *repo) diff --git a/trace2.h b/trace2.h index 4ced30c0db..f5c5a9e6ba 100644 --- a/trace2.h +++ b/trace2.h @@ -325,6 +325,7 @@ void trace2_thread_exit_fl(const char *file, int line); #define trace2_thread_exit() trace2_thread_exit_fl(__FILE__, __LINE__) +struct key_value_info; /* * Emits a "def_param" message containing a key/value pair. * @@ -334,7 +335,7 @@ void trace2_thread_exit_fl(const char *file, int line); * `core.abbrev`, `status.showUntrackedFiles`, or `--no-ahead-behind`. */ void trace2_def_param_fl(const char *file, int line, const char *param, - const char *value); + const char *value, const struct key_value_info *kvi); #define trace2_def_param(param, value) \ trace2_def_param_fl(__FILE__, __LINE__, (param), (value)) diff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c index 83bc4fd109..733d9d2872 100644 --- a/trace2/tr2_cfg.c +++ b/trace2/tr2_cfg.c @@ -100,7 +100,7 @@ struct tr2_cfg_data { * See if the given config key matches any of our patterns of interest. */ static int tr2_cfg_cb(const char *key, const char *value, - const struct config_context *ctx UNUSED, void *d) + const struct config_context *ctx, void *d) { struct strbuf **s; struct tr2_cfg_data *data = (struct tr2_cfg_data *)d; @@ -109,7 +109,8 @@ static int tr2_cfg_cb(const char *key, const char *value, struct strbuf *buf = *s; int wm = wildmatch(buf->buf, key, WM_CASEFOLD); if (wm == WM_MATCH) { - trace2_def_param_fl(data->file, data->line, key, value); + trace2_def_param_fl(data->file, data->line, key, value, + ctx->kvi); return 0; } } @@ -127,8 +128,10 @@ void tr2_cfg_list_config_fl(const char *file, int line) void tr2_list_env_vars_fl(const char *file, int line) { + struct key_value_info kvi = KVI_INIT; struct strbuf **s; + kvi_from_param(&kvi); if (tr2_load_env_vars() <= 0) return; @@ -136,7 +139,7 @@ void tr2_list_env_vars_fl(const char *file, int line) struct strbuf *buf = *s; const char *val = getenv(buf->buf); if (val && *val) - trace2_def_param_fl(file, line, buf->buf, val); + trace2_def_param_fl(file, line, buf->buf, val, &kvi); } } diff --git a/trace2/tr2_tgt.h b/trace2/tr2_tgt.h index bf8745c4f0..1f626cffea 100644 --- a/trace2/tr2_tgt.h +++ b/trace2/tr2_tgt.h @@ -69,8 +69,10 @@ typedef void(tr2_tgt_evt_exec_result_fl_t)(const char *file, int line, uint64_t us_elapsed_absolute, int exec_id, int code); +struct key_value_info; typedef void(tr2_tgt_evt_param_fl_t)(const char *file, int line, - const char *param, const char *value); + const char *param, const char *value, + const struct key_value_info *kvi); typedef void(tr2_tgt_evt_repo_fl_t)(const char *file, int line, const struct repository *repo); diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c index 2af53e5d4d..53091781ec 100644 --- a/trace2/tr2_tgt_event.c +++ b/trace2/tr2_tgt_event.c @@ -477,11 +477,11 @@ static void fn_exec_result_fl(const char *file, int line, } static void fn_param_fl(const char *file, int line, const char *param, - const char *value) + const char *value, const struct key_value_info *kvi) { const char *event_name = "def_param"; struct json_writer jw = JSON_WRITER_INIT; - enum config_scope scope = current_config_scope(); + enum config_scope scope = kvi->scope; const char *scope_name = config_scope_name(scope); jw_object_begin(&jw, 0); diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c index 1ebfb464d5..d25ea13164 100644 --- a/trace2/tr2_tgt_normal.c +++ b/trace2/tr2_tgt_normal.c @@ -297,10 +297,10 @@ static void fn_exec_result_fl(const char *file, int line, } static void fn_param_fl(const char *file, int line, const char *param, - const char *value) + const char *value, const struct key_value_info *kvi) { struct strbuf buf_payload = STRBUF_INIT; - enum config_scope scope = current_config_scope(); + enum config_scope scope = kvi->scope; const char *scope_name = config_scope_name(scope); strbuf_addf(&buf_payload, "def_param scope:%s %s=%s", scope_name, param, diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c index 328e483a05..a6f9a8a193 100644 --- a/trace2/tr2_tgt_perf.c +++ b/trace2/tr2_tgt_perf.c @@ -439,12 +439,12 @@ static void fn_exec_result_fl(const char *file, int line, } static void fn_param_fl(const char *file, int line, const char *param, - const char *value) + const char *value, const struct key_value_info *kvi) { const char *event_name = "def_param"; struct strbuf buf_payload = STRBUF_INIT; struct strbuf scope_payload = STRBUF_INIT; - enum config_scope scope = current_config_scope(); + enum config_scope scope = kvi->scope; const char *scope_name = config_scope_name(scope); strbuf_addf(&buf_payload, "%s:%s", param, value); -- cgit v1.3-5-g9baa From 8868b1ebfb8274a3ef90e1ba69ed45be94f6c3fb Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:27 +0000 Subject: config: pass kvi to die_bad_number() Plumb "struct key_value_info" through all code paths that end in die_bad_number(), which lets us remove the helper functions that read analogous values from "struct config_reader". As a result, nothing reads config_reader.config_kvi any more, so remove that too. In config.c, this requires changing the signature of git_configset_get_value() to 'return' "kvi" in an out parameter so that git_configset_get_() can pass it to git_config_(). Only numeric types will use "kvi", so for non-numeric types (e.g. git_configset_get_string()), pass NULL to indicate that the out parameter isn't needed. Outside of config.c, config callbacks now need to pass "ctx->kvi" to any of the git_config_() functions that parse a config string into a number type. Included is a .cocci patch to make that refactor. The only exceptional case is builtin/config.c, where git_config_() is called outside of a config callback (namely, on user-provided input), so config source information has never been available. In this case, die_bad_number() defaults to a generic, but perfectly descriptive message. Let's provide a safe, non-NULL for "kvi" anyway, but make sure not to change the message. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- archive-tar.c | 4 +- builtin/commit-graph.c | 4 +- builtin/commit.c | 10 +- builtin/config.c | 21 ++-- builtin/fetch.c | 4 +- builtin/fsmonitor--daemon.c | 6 +- builtin/grep.c | 2 +- builtin/index-pack.c | 4 +- builtin/log.c | 2 +- builtin/pack-objects.c | 14 +-- builtin/receive-pack.c | 10 +- builtin/submodule--helper.c | 4 +- config.c | 156 +++++++++++------------------ config.h | 17 ++-- contrib/coccinelle/git_config_number.cocci | 27 +++++ diff.c | 9 +- fmt-merge-msg.c | 2 +- help.c | 4 +- http.c | 10 +- imap-send.c | 2 +- sequencer.c | 22 ++-- setup.c | 2 +- submodule-config.c | 13 +-- submodule-config.h | 3 +- t/helper/test-config.c | 6 +- upload-pack.c | 12 ++- worktree.c | 2 +- 27 files changed, 190 insertions(+), 182 deletions(-) create mode 100644 contrib/coccinelle/git_config_number.cocci (limited to 'config.c') diff --git a/archive-tar.c b/archive-tar.c index ef06e516b1..3df8af6d1b 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -412,14 +412,14 @@ static int tar_filter_config(const char *var, const char *value, } static int git_tar_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, void *cb) + const struct config_context *ctx, void *cb) { if (!strcmp(var, "tar.umask")) { if (value && !strcmp(value, "user")) { tar_umask = umask(0); umask(tar_umask); } else { - tar_umask = git_config_int(var, value); + tar_umask = git_config_int(var, value, ctx->kvi); } return 0; } diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 1185c49239..b071c5ab64 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -186,11 +186,11 @@ static int write_option_max_new_filters(const struct option *opt, } static int git_commit_graph_write_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb UNUSED) { if (!strcmp(var, "commitgraph.maxnewfilters")) - write_opts.max_new_filters = git_config_int(var, value); + write_opts.max_new_filters = git_config_int(var, value, ctx->kvi); /* * No need to fall-back to 'git_default_config', since this was already * called in 'cmd_commit_graph()'. diff --git a/builtin/commit.c b/builtin/commit.c index 6a2b250332..9fe691470a 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1415,7 +1415,8 @@ static int git_status_config(const char *k, const char *v, return git_column_config(k, v, "status", &s->colopts); if (!strcmp(k, "status.submodulesummary")) { int is_bool; - s->submodule_summary = git_config_bool_or_int(k, v, &is_bool); + s->submodule_summary = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); if (is_bool && s->submodule_summary) s->submodule_summary = -1; return 0; @@ -1475,11 +1476,11 @@ static int git_status_config(const char *k, const char *v, } if (!strcmp(k, "diff.renamelimit")) { if (s->rename_limit == -1) - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "status.renamelimit")) { - s->rename_limit = git_config_int(k, v); + s->rename_limit = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "diff.renames")) { @@ -1625,7 +1626,8 @@ static int git_commit_config(const char *k, const char *v, } if (!strcmp(k, "commit.verbose")) { int is_bool; - config_commit_verbose = git_config_bool_or_int(k, v, &is_bool); + config_commit_verbose = git_config_bool_or_int(k, v, ctx->kvi, + &is_bool); return 0; } diff --git a/builtin/config.c b/builtin/config.c index 9b9f552731..680269d263 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -262,13 +262,14 @@ static int format_config(struct strbuf *buf, const char *key_, if (type == TYPE_INT) strbuf_addf(buf, "%"PRId64, - git_config_int64(key_, value_ ? value_ : "")); + git_config_int64(key_, value_ ? value_ : "", kvi)); else if (type == TYPE_BOOL) strbuf_addstr(buf, git_config_bool(key_, value_) ? "true" : "false"); else if (type == TYPE_BOOL_OR_INT) { int is_bool, v; - v = git_config_bool_or_int(key_, value_, &is_bool); + v = git_config_bool_or_int(key_, value_, kvi, + &is_bool); if (is_bool) strbuf_addstr(buf, v ? "true" : "false"); else @@ -424,7 +425,8 @@ free_strings: return ret; } -static char *normalize_value(const char *key, const char *value) +static char *normalize_value(const char *key, const char *value, + struct key_value_info *kvi) { if (!value) return NULL; @@ -439,12 +441,12 @@ static char *normalize_value(const char *key, const char *value) */ return xstrdup(value); if (type == TYPE_INT) - return xstrfmt("%"PRId64, git_config_int64(key, value)); + return xstrfmt("%"PRId64, git_config_int64(key, value, kvi)); if (type == TYPE_BOOL) return xstrdup(git_config_bool(key, value) ? "true" : "false"); if (type == TYPE_BOOL_OR_INT) { int is_bool, v; - v = git_config_bool_or_int(key, value, &is_bool); + v = git_config_bool_or_int(key, value, kvi, &is_bool); if (!is_bool) return xstrfmt("%d", v); else @@ -674,6 +676,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) char *value = NULL; int flags = 0; int ret = 0; + struct key_value_info default_kvi = KVI_INIT; given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT)); @@ -891,7 +894,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_SET) { check_write(); check_argc(argc, 2, 2); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value); if (ret == CONFIG_NOTHING_SET) error(_("cannot overwrite multiple values with a single value\n" @@ -900,7 +903,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_SET_ALL) { check_write(); check_argc(argc, 2, 3); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], flags); @@ -908,7 +911,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_ADD) { check_write(); check_argc(argc, 2, 2); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, CONFIG_REGEX_NONE, @@ -917,7 +920,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (actions == ACTION_REPLACE_ALL) { check_write(); check_argc(argc, 2, 3); - value = normalize_value(argv[0], argv[1]); + value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], flags | CONFIG_FLAGS_MULTI_REPLACE); diff --git a/builtin/fetch.c b/builtin/fetch.c index a4aa0fbb8f..fe86dfeb62 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -137,7 +137,7 @@ static int git_fetch_config(const char *k, const char *v, } if (!strcmp(k, "submodule.fetchjobs")) { - fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v); + fetch_config->submodule_fetch_jobs = parse_submodule_fetchjobs(k, v, ctx->kvi); return 0; } else if (!strcmp(k, "fetch.recursesubmodules")) { fetch_config->recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); @@ -145,7 +145,7 @@ static int git_fetch_config(const char *k, const char *v, } if (!strcmp(k, "fetch.parallel")) { - fetch_config->parallel = git_config_int(k, v); + fetch_config->parallel = git_config_int(k, v, ctx->kvi); if (fetch_config->parallel < 0) die(_("fetch.parallel cannot be negative")); if (!fetch_config->parallel) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 91a776e2f1..6d2826b07d 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -41,7 +41,7 @@ static int fsmonitor_config(const char *var, const char *value, const struct config_context *ctx, void *cb) { if (!strcmp(var, FSMONITOR__IPC_THREADS)) { - int i = git_config_int(var, value); + int i = git_config_int(var, value, ctx->kvi); if (i < 1) return error(_("value of '%s' out of range: %d"), FSMONITOR__IPC_THREADS, i); @@ -50,7 +50,7 @@ static int fsmonitor_config(const char *var, const char *value, } if (!strcmp(var, FSMONITOR__START_TIMEOUT)) { - int i = git_config_int(var, value); + int i = git_config_int(var, value, ctx->kvi); if (i < 0) return error(_("value of '%s' out of range: %d"), FSMONITOR__START_TIMEOUT, i); @@ -60,7 +60,7 @@ static int fsmonitor_config(const char *var, const char *value, if (!strcmp(var, FSMONITOR__ANNOUNCE_STARTUP)) { int is_bool; - int i = git_config_bool_or_int(var, value, &is_bool); + int i = git_config_bool_or_int(var, value, ctx->kvi, &is_bool); if (i < 0) return error(_("value of '%s' not bool or int: %d"), var, i); diff --git a/builtin/grep.c b/builtin/grep.c index 757d52b94e..3a464e6faa 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -301,7 +301,7 @@ static int grep_cmd_config(const char *var, const char *value, st = -1; if (!strcmp(var, "grep.threads")) { - num_threads = git_config_int(var, value); + num_threads = git_config_int(var, value, ctx->kvi); if (num_threads < 0) die(_("invalid number of threads specified (%d) for %s"), num_threads, var); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index de8884ea5c..e428f6d9a4 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1587,13 +1587,13 @@ static int git_index_pack_config(const char *k, const char *v, struct pack_idx_option *opts = cb; if (!strcmp(k, "pack.indexversion")) { - opts->version = git_config_int(k, v); + opts->version = git_config_int(k, v, ctx->kvi); if (opts->version > 2) die(_("bad pack.indexVersion=%"PRIu32), opts->version); return 0; } if (!strcmp(k, "pack.threads")) { - nr_threads = git_config_int(k, v); + nr_threads = git_config_int(k, v, ctx->kvi); if (nr_threads < 0) die(_("invalid number of threads specified (%d)"), nr_threads); diff --git a/builtin/log.c b/builtin/log.c index 09d6a13075..c7337354aa 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -574,7 +574,7 @@ static int git_log_config(const char *var, const char *value, if (!strcmp(var, "format.subjectprefix")) return git_config_string(&fmt_patch_subject_prefix, var, value); if (!strcmp(var, "format.filenamemaxlength")) { - fmt_patch_name_max = git_config_int(var, value); + fmt_patch_name_max = git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp(var, "format.encodeemailheaders")) { diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 34aa0b483a..38054a38b2 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -3139,23 +3139,23 @@ static int git_pack_config(const char *k, const char *v, const struct config_context *ctx, void *cb) { if (!strcmp(k, "pack.window")) { - window = git_config_int(k, v); + window = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.windowmemory")) { - window_memory_limit = git_config_ulong(k, v); + window_memory_limit = git_config_ulong(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.depth")) { - depth = git_config_int(k, v); + depth = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.deltacachesize")) { - max_delta_cache_size = git_config_int(k, v); + max_delta_cache_size = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.deltacachelimit")) { - cache_max_small_delta_size = git_config_int(k, v); + cache_max_small_delta_size = git_config_int(k, v, ctx->kvi); return 0; } if (!strcmp(k, "pack.writebitmaphashcache")) { @@ -3181,7 +3181,7 @@ static int git_pack_config(const char *k, const char *v, return 0; } if (!strcmp(k, "pack.threads")) { - delta_search_threads = git_config_int(k, v); + delta_search_threads = git_config_int(k, v, ctx->kvi); if (delta_search_threads < 0) die(_("invalid number of threads specified (%d)"), delta_search_threads); @@ -3192,7 +3192,7 @@ static int git_pack_config(const char *k, const char *v, return 0; } if (!strcmp(k, "pack.indexversion")) { - pack_idx_opts.version = git_config_int(k, v); + pack_idx_opts.version = git_config_int(k, v, ctx->kvi); if (pack_idx_opts.version > 2) die(_("bad pack.indexVersion=%"PRIu32), pack_idx_opts.version); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 94d9898aff..98f6f0038f 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -158,12 +158,12 @@ static int receive_pack_config(const char *var, const char *value, } if (strcmp(var, "receive.unpacklimit") == 0) { - receive_unpack_limit = git_config_int(var, value); + receive_unpack_limit = git_config_int(var, value, ctx->kvi); return 0; } if (strcmp(var, "transfer.unpacklimit") == 0) { - transfer_unpack_limit = git_config_int(var, value); + transfer_unpack_limit = git_config_int(var, value, ctx->kvi); return 0; } @@ -231,7 +231,7 @@ static int receive_pack_config(const char *var, const char *value, return git_config_string(&cert_nonce_seed, var, value); if (strcmp(var, "receive.certnonceslop") == 0) { - nonce_stamp_slop_limit = git_config_ulong(var, value); + nonce_stamp_slop_limit = git_config_ulong(var, value, ctx->kvi); return 0; } @@ -246,12 +246,12 @@ static int receive_pack_config(const char *var, const char *value, } if (strcmp(var, "receive.keepalive") == 0) { - keepalive_in_sec = git_config_int(var, value); + keepalive_in_sec = git_config_int(var, value, ctx->kvi); return 0; } if (strcmp(var, "receive.maxinputsize") == 0) { - max_input_size = git_config_int64(var, value); + max_input_size = git_config_int64(var, value, ctx->kvi); return 0; } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f8e9d85e77..57185cf5f3 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -2192,13 +2192,13 @@ static int update_clone_task_finished(int result, } static int git_update_clone_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb) { int *max_jobs = cb; if (!strcmp(var, "submodule.fetchjobs")) - *max_jobs = parse_submodule_fetchjobs(var, value); + *max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi); return 0; } diff --git a/config.c b/config.c index d10faba56d..4e3c4dcf41 100644 --- a/config.c +++ b/config.c @@ -73,18 +73,8 @@ struct config_reader { * * The "source" variable will be non-NULL only when we are actually * parsing a real config source (file, blob, cmdline, etc). - * - * The "config_kvi" variable will be non-NULL only when we are feeding - * cached config from a configset into a callback. - * - * They cannot be non-NULL at the same time. If they are both NULL, then - * we aren't parsing anything (and depending on the function looking at - * the variables, it's either a bug for it to be called in the first - * place, or it's a function which can be reused for non-config - * purposes, and should fall back to some sane behavior). */ struct config_source *source; - struct key_value_info *config_kvi; }; /* * Where possible, prefer to accept "struct config_reader" as an arg than to use @@ -96,8 +86,6 @@ static struct config_reader the_reader; static inline void config_reader_push_source(struct config_reader *reader, struct config_source *top) { - if (reader->config_kvi) - BUG("source should not be set while iterating a config set"); top->prev = reader->source; reader->source = top; } @@ -112,12 +100,6 @@ static inline struct config_source *config_reader_pop_source(struct config_reade return ret; } -static inline void config_reader_set_kvi(struct config_reader *reader, - struct key_value_info *kvi) -{ - reader->config_kvi = kvi; -} - static int pack_compression_seen; static int zlib_compression_seen; @@ -1346,80 +1328,78 @@ 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_reader *reader, const char *name, - const char *value) +static void die_bad_number(const char *name, const char *value, + const struct key_value_info *kvi) { 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 (!kvi) + BUG("kvi should not be NULL"); if (!value) value = ""; - /* 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) + if (!kvi->filename) die(_(bad_numeric), value, name, _(error_type)); - switch (config_origin) { + switch (kvi->origin_type) { case CONFIG_ORIGIN_BLOB: die(_("bad numeric config value '%s' for '%s' in blob %s: %s"), - value, name, config_name, _(error_type)); + value, name, kvi->filename, _(error_type)); case CONFIG_ORIGIN_FILE: die(_("bad numeric config value '%s' for '%s' in file %s: %s"), - value, name, config_name, _(error_type)); + value, name, kvi->filename, _(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, config_name, _(error_type)); + value, name, kvi->filename, _(error_type)); case CONFIG_ORIGIN_CMDLINE: die(_("bad numeric config value '%s' for '%s' in command line %s: %s"), - value, name, config_name, _(error_type)); + value, name, kvi->filename, _(error_type)); default: die(_("bad numeric config value '%s' for '%s' in %s: %s"), - value, name, config_name, _(error_type)); + value, name, kvi->filename, _(error_type)); } } -int git_config_int(const char *name, const char *value) +int git_config_int(const char *name, const char *value, + const struct key_value_info *kvi) { int ret; if (!git_parse_int(value, &ret)) - die_bad_number(&the_reader, name, value); + die_bad_number(name, value, kvi); return ret; } -int64_t git_config_int64(const char *name, const char *value) +int64_t git_config_int64(const char *name, const char *value, + const struct key_value_info *kvi) { int64_t ret; if (!git_parse_int64(value, &ret)) - die_bad_number(&the_reader, name, value); + die_bad_number(name, value, kvi); return ret; } -unsigned long git_config_ulong(const char *name, const char *value) +unsigned long git_config_ulong(const char *name, const char *value, + const struct key_value_info *kvi) { unsigned long ret; if (!git_parse_ulong(value, &ret)) - die_bad_number(&the_reader, name, value); + die_bad_number(name, value, kvi); return ret; } -ssize_t git_config_ssize_t(const char *name, const char *value) +ssize_t git_config_ssize_t(const char *name, const char *value, + const struct key_value_info *kvi) { ssize_t ret; if (!git_parse_ssize_t(value, &ret)) - die_bad_number(&the_reader, name, value); + die_bad_number(name, value, kvi); return ret; } @@ -1524,7 +1504,8 @@ int git_parse_maybe_bool(const char *value) return -1; } -int git_config_bool_or_int(const char *name, const char *value, int *is_bool) +int git_config_bool_or_int(const char *name, const char *value, + const struct key_value_info *kvi, int *is_bool) { int v = git_parse_maybe_bool_text(value); if (0 <= v) { @@ -1532,7 +1513,7 @@ int git_config_bool_or_int(const char *name, const char *value, int *is_bool) return v; } *is_bool = 0; - return git_config_int(name, value); + return git_config_int(name, value, kvi); } int git_config_bool(const char *name, const char *value) @@ -1658,7 +1639,7 @@ static int git_default_core_config(const char *var, const char *value, else if (!git_parse_maybe_bool_text(value)) default_abbrev = the_hash_algo->hexsz; else { - int abbrev = git_config_int(var, value); + int abbrev = git_config_int(var, value, ctx->kvi); if (abbrev < minimum_abbrev || abbrev > the_hash_algo->hexsz) return error(_("abbrev length out of range: %d"), abbrev); default_abbrev = abbrev; @@ -1670,7 +1651,7 @@ static int git_default_core_config(const char *var, const char *value, return set_disambiguate_hint_config(var, value); if (!strcmp(var, "core.loosecompression")) { - int level = git_config_int(var, value); + int level = git_config_int(var, value, ctx->kvi); if (level == -1) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) @@ -1681,7 +1662,7 @@ static int git_default_core_config(const char *var, const char *value, } if (!strcmp(var, "core.compression")) { - int level = git_config_int(var, value); + int level = git_config_int(var, value, ctx->kvi); if (level == -1) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) @@ -1695,7 +1676,7 @@ static int git_default_core_config(const char *var, const char *value, if (!strcmp(var, "core.packedgitwindowsize")) { int pgsz_x2 = getpagesize() * 2; - packed_git_window_size = git_config_ulong(var, value); + packed_git_window_size = git_config_ulong(var, value, ctx->kvi); /* This value must be multiple of (pagesize * 2) */ packed_git_window_size /= pgsz_x2; @@ -1706,17 +1687,17 @@ static int git_default_core_config(const char *var, const char *value, } if (!strcmp(var, "core.bigfilethreshold")) { - big_file_threshold = git_config_ulong(var, value); + big_file_threshold = git_config_ulong(var, value, ctx->kvi); return 0; } if (!strcmp(var, "core.packedgitlimit")) { - packed_git_limit = git_config_ulong(var, value); + packed_git_limit = git_config_ulong(var, value, ctx->kvi); return 0; } if (!strcmp(var, "core.deltabasecachelimit")) { - delta_base_cache_limit = git_config_ulong(var, value); + delta_base_cache_limit = git_config_ulong(var, value, ctx->kvi); return 0; } @@ -1995,12 +1976,12 @@ int git_default_config(const char *var, const char *value, } if (!strcmp(var, "pack.packsizelimit")) { - pack_size_limit_cfg = git_config_ulong(var, value); + pack_size_limit_cfg = git_config_ulong(var, value, ctx->kvi); return 0; } if (!strcmp(var, "pack.compression")) { - int level = git_config_int(var, value); + int level = git_config_int(var, value, ctx->kvi); if (level == -1) level = Z_DEFAULT_COMPRESSION; else if (level < 0 || level > Z_BEST_COMPRESSION) @@ -2344,13 +2325,11 @@ static void configset_iter(struct config_reader *reader, struct config_set *set, value_index = list->items[i].value_index; values = &entry->value_list; - config_reader_set_kvi(reader, values->items[value_index].util); ctx.kvi = values->items[value_index].util; if (fn(entry->key, values->items[value_index].string, &ctx, data) < 0) git_die_config_linenr(entry->key, ctx.kvi->filename, ctx.kvi->linenr); - config_reader_set_kvi(reader, NULL); } } @@ -2536,11 +2515,12 @@ int git_configset_add_file(struct config_set *set, const char *filename) return git_config_from_file(config_set_callback, filename, &data); } -int git_configset_get_value(struct config_set *set, const char *key, const char **value) +int git_configset_get_value(struct config_set *set, const char *key, + const char **value, struct key_value_info *kvi) { const struct string_list *values = NULL; int ret; - + struct string_list_item item; /* * Follows "last one wins" semantic, i.e., if there are multiple matches for the * queried key in the files of the configset, the value returned will be the last @@ -2550,7 +2530,10 @@ int git_configset_get_value(struct config_set *set, const char *key, const char return ret; assert(values->nr > 0); - *value = values->items[values->nr - 1].string; + item = values->items[values->nr - 1]; + *value = item.string; + if (kvi) + *kvi = *((struct key_value_info *)item.util); return 0; } @@ -2603,7 +2586,7 @@ int git_configset_get(struct config_set *set, const char *key) int git_configset_get_string(struct config_set *set, const char *key, char **dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) + if (!git_configset_get_value(set, key, &value, NULL)) return git_config_string((const char **)dest, key, value); else return 1; @@ -2613,7 +2596,7 @@ static int git_configset_get_string_tmp(struct config_set *set, const char *key, const char **dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { + if (!git_configset_get_value(set, key, &value, NULL)) { if (!value) return config_error_nonbool(key); *dest = value; @@ -2626,8 +2609,10 @@ static int git_configset_get_string_tmp(struct config_set *set, const char *key, int git_configset_get_int(struct config_set *set, const char *key, int *dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { - *dest = git_config_int(key, value); + struct key_value_info kvi; + + if (!git_configset_get_value(set, key, &value, &kvi)) { + *dest = git_config_int(key, value, &kvi); return 0; } else return 1; @@ -2636,8 +2621,10 @@ int git_configset_get_int(struct config_set *set, const char *key, int *dest) int git_configset_get_ulong(struct config_set *set, const char *key, unsigned long *dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { - *dest = git_config_ulong(key, value); + struct key_value_info kvi; + + if (!git_configset_get_value(set, key, &value, &kvi)) { + *dest = git_config_ulong(key, value, &kvi); return 0; } else return 1; @@ -2646,7 +2633,7 @@ int git_configset_get_ulong(struct config_set *set, const char *key, unsigned lo int git_configset_get_bool(struct config_set *set, const char *key, int *dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { + if (!git_configset_get_value(set, key, &value, NULL)) { *dest = git_config_bool(key, value); return 0; } else @@ -2657,8 +2644,10 @@ int git_configset_get_bool_or_int(struct config_set *set, const char *key, int *is_bool, int *dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { - *dest = git_config_bool_or_int(key, value, is_bool); + struct key_value_info kvi; + + if (!git_configset_get_value(set, key, &value, &kvi)) { + *dest = git_config_bool_or_int(key, value, &kvi, is_bool); return 0; } else return 1; @@ -2667,7 +2656,7 @@ int git_configset_get_bool_or_int(struct config_set *set, const char *key, int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) { + if (!git_configset_get_value(set, key, &value, NULL)) { *dest = git_parse_maybe_bool(value); if (*dest == -1) return -1; @@ -2679,7 +2668,7 @@ int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *d int git_configset_get_pathname(struct config_set *set, const char *key, const char **dest) { const char *value; - if (!git_configset_get_value(set, key, &value)) + if (!git_configset_get_value(set, key, &value, NULL)) return git_config_pathname(dest, key, value); else return 1; @@ -2749,7 +2738,7 @@ int repo_config_get_value(struct repository *repo, const char *key, const char **value) { git_config_check_init(repo); - return git_configset_get_value(repo->config, key, value); + return git_configset_get_value(repo->config, key, value, NULL); } int repo_config_get_value_multi(struct repository *repo, const char *key, @@ -3989,18 +3978,6 @@ 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 *config_origin_type_name(enum config_origin_type type) { switch (type) { @@ -4039,17 +4016,6 @@ 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; -} - int lookup_config(const char **mapping, int nr_mapping, const char *var) { int i; diff --git a/config.h b/config.h index 82eeba94e7..bd366ddb5e 100644 --- a/config.h +++ b/config.h @@ -249,22 +249,26 @@ int git_parse_maybe_bool(const char *); * Parse the string to an integer, including unit factors. Dies on error; * otherwise, returns the parsed result. */ -int git_config_int(const char *, const char *); +int git_config_int(const char *, const char *, const struct key_value_info *); -int64_t git_config_int64(const char *, const char *); +int64_t git_config_int64(const char *, const char *, + const struct key_value_info *); /** * Identical to `git_config_int`, but for unsigned longs. */ -unsigned long git_config_ulong(const char *, const char *); +unsigned long git_config_ulong(const char *, const char *, + const struct key_value_info *); -ssize_t git_config_ssize_t(const char *, const char *); +ssize_t git_config_ssize_t(const char *, const char *, + const struct key_value_info *); /** * Same as `git_config_bool`, except that integers are returned as-is, and * an `is_bool` flag is unset. */ -int git_config_bool_or_int(const char *, const char *, int *); +int git_config_bool_or_int(const char *, const char *, + const struct key_value_info *, int *); /** * Parse a string into a boolean value, respecting keywords like "true" and @@ -529,7 +533,8 @@ int git_configset_get(struct config_set *cs, const char *key); * touching `value`. The caller should not free or modify `value`, as it * is owned by the cache. */ -int git_configset_get_value(struct config_set *cs, const char *key, const char **dest); +int git_configset_get_value(struct config_set *cs, const char *key, + const char **dest, struct key_value_info *kvi); int git_configset_get_string(struct config_set *cs, const char *key, char **dest); int git_configset_get_int(struct config_set *cs, const char *key, int *dest); diff --git a/contrib/coccinelle/git_config_number.cocci b/contrib/coccinelle/git_config_number.cocci new file mode 100644 index 0000000000..7b57dceefe --- /dev/null +++ b/contrib/coccinelle/git_config_number.cocci @@ -0,0 +1,27 @@ +@@ +identifier C1, C2, C3; +@@ +( +( +git_config_int +| +git_config_int64 +| +git_config_ulong +| +git_config_ssize_t +) + (C1, C2 ++ , ctx->kvi + ) +| +( +git_configset_get_value +| +git_config_bool_or_int +) + (C1, C2 ++ , ctx->kvi + , C3 + ) +) diff --git a/diff.c b/diff.c index 0e382c8f7f..460211e7d4 100644 --- a/diff.c +++ b/diff.c @@ -379,13 +379,14 @@ int git_diff_ui_config(const char *var, const char *value, return 0; } if (!strcmp(var, "diff.context")) { - diff_context_default = git_config_int(var, value); + diff_context_default = git_config_int(var, value, ctx->kvi); if (diff_context_default < 0) return -1; return 0; } if (!strcmp(var, "diff.interhunkcontext")) { - diff_interhunk_context_default = git_config_int(var, value); + diff_interhunk_context_default = git_config_int(var, value, + ctx->kvi); if (diff_interhunk_context_default < 0) return -1; return 0; @@ -411,7 +412,7 @@ int git_diff_ui_config(const char *var, const char *value, return 0; } if (!strcmp(var, "diff.statgraphwidth")) { - diff_stat_graph_width = git_config_int(var, value); + diff_stat_graph_width = git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp(var, "diff.external")) @@ -450,7 +451,7 @@ int git_diff_basic_config(const char *var, const char *value, const char *name; if (!strcmp(var, "diff.renamelimit")) { - diff_rename_limit_default = git_config_int(var, value); + diff_rename_limit_default = git_config_int(var, value, ctx->kvi); return 0; } diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c index 1013744432..3ae59bde2f 100644 --- a/fmt-merge-msg.c +++ b/fmt-merge-msg.c @@ -25,7 +25,7 @@ int fmt_merge_msg_config(const char *key, const char *value, { if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) { int is_bool; - merge_log_config = git_config_bool_or_int(key, value, &is_bool); + merge_log_config = git_config_bool_or_int(key, value, ctx->kvi, &is_bool); if (!is_bool && merge_log_config < 0) return error("%s: negative length %s", key, value); if (is_bool && merge_log_config) diff --git a/help.c b/help.c index ac0ae5ac0d..389382b148 100644 --- a/help.c +++ b/help.c @@ -545,7 +545,7 @@ static struct cmdnames aliases; #define AUTOCORRECT_IMMEDIATELY (-1) static int git_unknown_cmd_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb UNUSED) { const char *p; @@ -560,7 +560,7 @@ static int git_unknown_cmd_config(const char *var, const char *value, } else if (!strcmp(value, "prompt")) { autocorrect = AUTOCORRECT_PROMPT; } else { - int v = git_config_int(var, value); + int v = git_config_int(var, value, ctx->kvi); autocorrect = (v < 0) ? AUTOCORRECT_IMMEDIATELY : v; } diff --git a/http.c b/http.c index 762502828c..b12b234bde 100644 --- a/http.c +++ b/http.c @@ -414,21 +414,21 @@ static int http_options(const char *var, const char *value, } if (!strcmp("http.minsessions", var)) { - min_curl_sessions = git_config_int(var, value); + min_curl_sessions = git_config_int(var, value, ctx->kvi); if (min_curl_sessions > 1) min_curl_sessions = 1; return 0; } if (!strcmp("http.maxrequests", var)) { - max_requests = git_config_int(var, value); + max_requests = git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp("http.lowspeedlimit", var)) { - curl_low_speed_limit = (long)git_config_int(var, value); + curl_low_speed_limit = (long)git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp("http.lowspeedtime", var)) { - curl_low_speed_time = (long)git_config_int(var, value); + curl_low_speed_time = (long)git_config_int(var, value, ctx->kvi); return 0; } @@ -464,7 +464,7 @@ static int http_options(const char *var, const char *value, } if (!strcmp("http.postbuffer", var)) { - http_post_buffer = git_config_ssize_t(var, value); + http_post_buffer = git_config_ssize_t(var, value, ctx->kvi); if (http_post_buffer < 0) warning(_("negative value for http.postBuffer; defaulting to %d"), LARGE_PACKET_MAX); if (http_post_buffer < LARGE_PACKET_MAX) diff --git a/imap-send.c b/imap-send.c index 47777e7686..3518a4ace6 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1342,7 +1342,7 @@ static int git_imap_config(const char *var, const char *val, else if (!strcmp("imap.authmethod", var)) return git_config_string(&server.auth_method, var, val); else if (!strcmp("imap.port", var)) - server.port = git_config_int(var, val); + server.port = git_config_int(var, val, ctx->kvi); else if (!strcmp("imap.host", var)) { if (!val) { git_die_config("imap.host", "Missing value for 'imap.host'"); diff --git a/sequencer.c b/sequencer.c index 34754d1759..a0aaee3056 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2883,7 +2883,7 @@ static int git_config_string_dup(char **dest, } static int populate_opts_cb(const char *key, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *data) { struct replay_opts *opts = data; @@ -2892,26 +2892,26 @@ static int populate_opts_cb(const char *key, const char *value, if (!value) error_flag = 0; else if (!strcmp(key, "options.no-commit")) - opts->no_commit = git_config_bool_or_int(key, value, &error_flag); + opts->no_commit = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.edit")) - opts->edit = git_config_bool_or_int(key, value, &error_flag); + opts->edit = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.allow-empty")) opts->allow_empty = - git_config_bool_or_int(key, value, &error_flag); + git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.allow-empty-message")) opts->allow_empty_message = - git_config_bool_or_int(key, value, &error_flag); + git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.keep-redundant-commits")) opts->keep_redundant_commits = - git_config_bool_or_int(key, value, &error_flag); + git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.signoff")) - opts->signoff = git_config_bool_or_int(key, value, &error_flag); + opts->signoff = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.record-origin")) - opts->record_origin = git_config_bool_or_int(key, value, &error_flag); + opts->record_origin = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.allow-ff")) - opts->allow_ff = git_config_bool_or_int(key, value, &error_flag); + opts->allow_ff = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.mainline")) - opts->mainline = git_config_int(key, value); + opts->mainline = git_config_int(key, value, ctx->kvi); else if (!strcmp(key, "options.strategy")) git_config_string_dup(&opts->strategy, key, value); else if (!strcmp(key, "options.gpg-sign")) @@ -2920,7 +2920,7 @@ static int populate_opts_cb(const char *key, const char *value, strvec_push(&opts->xopts, value); } else if (!strcmp(key, "options.allow-rerere-auto")) opts->allow_rerere_auto = - git_config_bool_or_int(key, value, &error_flag) ? + git_config_bool_or_int(key, value, ctx->kvi, &error_flag) ? RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE; else if (!strcmp(key, "options.default-msg-cleanup")) { opts->explicit_cleanup = 1; diff --git a/setup.c b/setup.c index fadba5bab4..ca80fb464b 100644 --- a/setup.c +++ b/setup.c @@ -597,7 +597,7 @@ static int check_repo_format(const char *var, const char *value, const char *ext; if (strcmp(var, "core.repositoryformatversion") == 0) - data->version = git_config_int(var, value); + data->version = git_config_int(var, value, ctx->kvi); else if (skip_prefix(var, "extensions.", &ext)) { switch (handle_extension_v0(var, value, ext, data)) { case EXTENSION_ERROR: diff --git a/submodule-config.c b/submodule-config.c index 3f25bd1367..54be580e2a 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -304,9 +304,10 @@ static int parse_fetch_recurse(const char *opt, const char *arg, } } -int parse_submodule_fetchjobs(const char *var, const char *value) +int parse_submodule_fetchjobs(const char *var, const char *value, + const struct key_value_info *kvi) { - int fetchjobs = git_config_int(var, value); + int fetchjobs = git_config_int(var, value, kvi); if (fetchjobs < 0) die(_("negative values not allowed for submodule.fetchJobs")); if (!fetchjobs) @@ -849,14 +850,14 @@ struct fetch_config { }; static int gitmodules_fetch_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb) { struct fetch_config *config = cb; if (!strcmp(var, "submodule.fetchjobs")) { if (config->max_children) *(config->max_children) = - parse_submodule_fetchjobs(var, value); + parse_submodule_fetchjobs(var, value, ctx->kvi); return 0; } else if (!strcmp(var, "fetch.recursesubmodules")) { if (config->recurse_submodules) @@ -878,12 +879,12 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules) } static int gitmodules_update_clone_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb) { int *max_jobs = cb; if (!strcmp(var, "submodule.fetchjobs")) - *max_jobs = parse_submodule_fetchjobs(var, value); + *max_jobs = parse_submodule_fetchjobs(var, value, ctx->kvi); return 0; } diff --git a/submodule-config.h b/submodule-config.h index c2045875bb..2a37689cc2 100644 --- a/submodule-config.h +++ b/submodule-config.h @@ -50,7 +50,8 @@ struct repository; void submodule_cache_free(struct submodule_cache *cache); -int parse_submodule_fetchjobs(const char *var, const char *value); +int parse_submodule_fetchjobs(const char *var, const char *value, + const struct key_value_info *kvi); int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg); struct option; int option_fetch_parse_recurse_submodules(const struct option *opt, diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 3f4c367831..ed444ca4c2 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -63,12 +63,12 @@ static int iterate_cb(const char *var, const char *value, } static int parse_int_cb(const char *var, const char *value, - const struct config_context *ctx UNUSED, void *data) + const struct config_context *ctx, void *data) { const char *key_to_match = data; if (!strcmp(key_to_match, var)) { - int parsed = git_config_int(value, value); + int parsed = git_config_int(value, value, ctx->kvi); printf("%d\n", parsed); } return 0; @@ -182,7 +182,7 @@ int cmd__config(int argc, const char **argv) goto exit2; } } - if (!git_configset_get_value(&cs, argv[2], &v)) { + if (!git_configset_get_value(&cs, argv[2], &v, NULL)) { if (!v) printf("(NULL)\n"); else diff --git a/upload-pack.c b/upload-pack.c index 951fd1f9c2..c03415a546 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -1275,7 +1275,8 @@ static int find_symref(const char *refname, } static int parse_object_filter_config(const char *var, const char *value, - struct upload_pack_data *data) + const struct key_value_info *kvi, + struct upload_pack_data *data) { struct strbuf buf = STRBUF_INIT; const char *sub, *key; @@ -1302,7 +1303,8 @@ static int parse_object_filter_config(const char *var, const char *value, } string_list_insert(&data->allowed_filters, buf.buf)->util = (void *)(intptr_t)1; - data->tree_filter_max_depth = git_config_ulong(var, value); + data->tree_filter_max_depth = git_config_ulong(var, value, + kvi); } strbuf_release(&buf); @@ -1310,7 +1312,7 @@ static int parse_object_filter_config(const char *var, const char *value, } static int upload_pack_config(const char *var, const char *value, - const struct config_context *ctx UNUSED, + const struct config_context *ctx, void *cb_data) { struct upload_pack_data *data = cb_data; @@ -1331,7 +1333,7 @@ static int upload_pack_config(const char *var, const char *value, else data->allow_uor &= ~ALLOW_ANY_SHA1; } else if (!strcmp("uploadpack.keepalive", var)) { - data->keepalive = git_config_int(var, value); + data->keepalive = git_config_int(var, value, ctx->kvi); if (!data->keepalive) data->keepalive = -1; } else if (!strcmp("uploadpack.allowfilter", var)) { @@ -1346,7 +1348,7 @@ static int upload_pack_config(const char *var, const char *value, data->advertise_sid = git_config_bool(var, value); } - if (parse_object_filter_config(var, value, data) < 0) + if (parse_object_filter_config(var, value, ctx->kvi, data) < 0) return -1; return parse_hide_refs_config(var, value, "uploadpack", &data->hidden_refs); diff --git a/worktree.c b/worktree.c index c448fecd4b..af277ec901 100644 --- a/worktree.c +++ b/worktree.c @@ -835,7 +835,7 @@ int init_worktree_config(struct repository *r) * Relocate that value to avoid breaking all worktrees with this * upgrade to worktree config. */ - if (!git_configset_get_value(&cs, "core.worktree", &core_worktree)) { + if (!git_configset_get_value(&cs, "core.worktree", &core_worktree, NULL)) { if ((res = move_config_setting("core.worktree", core_worktree, common_config_file, main_worktree_file))) -- cgit v1.3-5-g9baa From f6c213a0cbf7071c845eef0afa4bc5f9c4883e51 Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:28 +0000 Subject: config.c: remove config_reader from configsets Remove the last usage of "struct config_reader" from configsets by copying the "kvi" arg instead of recomputing "kvi" from config_reader.source. Since we no longer need to pass both "struct config_reader" and "struct config_set" in a single "void *cb", remove "struct configset_add_data" too. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- config.c | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 4e3c4dcf41..50dbd89a6d 100644 --- a/config.c +++ b/config.c @@ -2311,8 +2311,7 @@ int config_with_options(config_fn_t fn, void *data, return ret; } -static void configset_iter(struct config_reader *reader, struct config_set *set, - config_fn_t fn, void *data) +static void configset_iter(struct config_set *set, config_fn_t fn, void *data) { int i, value_index; struct string_list *values; @@ -2406,7 +2405,6 @@ static int configset_find_element(struct config_set *set, const char *key, } static int configset_add_value(const struct key_value_info *kvi_p, - struct config_reader *reader, struct config_set *set, const char *key, const char *value) { @@ -2437,13 +2435,7 @@ static int configset_add_value(const struct key_value_info *kvi_p, l_item->e = e; l_item->value_index = e->value_list.nr - 1; - if (!reader->source) - BUG("configset_add_value has no source"); - if (reader->source->name) { - kvi_from_source(reader->source, kvi_p->scope, kv_info); - } else { - kvi_from_param(kv_info); - } + *kv_info = *kvi_p; si->util = kv_info; return 0; @@ -2491,28 +2483,18 @@ void git_configset_clear(struct config_set *set) set->list.items = NULL; } -struct configset_add_data { - struct config_set *config_set; - struct config_reader *config_reader; -}; -#define CONFIGSET_ADD_INIT { 0 } - static int config_set_callback(const char *key, const char *value, const struct config_context *ctx, void *cb) { - struct configset_add_data *data = cb; - configset_add_value(ctx->kvi, data->config_reader, data->config_set, - key, value); + struct config_set *set = cb; + configset_add_value(ctx->kvi, set, key, value); return 0; } int git_configset_add_file(struct config_set *set, const char *filename) { - struct configset_add_data data = CONFIGSET_ADD_INIT; - data.config_reader = &the_reader; - data.config_set = set; - return git_config_from_file(config_set_callback, filename, &data); + return git_config_from_file(config_set_callback, filename, set); } int git_configset_get_value(struct config_set *set, const char *key, @@ -2678,7 +2660,6 @@ int git_configset_get_pathname(struct config_set *set, const char *key, const ch static void repo_read_config(struct repository *repo) { struct config_options opts = { 0 }; - struct configset_add_data data = CONFIGSET_ADD_INIT; opts.respect_includes = 1; opts.commondir = repo->commondir; @@ -2690,10 +2671,8 @@ static void repo_read_config(struct repository *repo) git_configset_clear(repo->config); git_configset_init(repo->config); - data.config_set = repo->config; - data.config_reader = &the_reader; - - if (config_with_options(config_set_callback, &data, NULL, repo, &opts) < 0) + if (config_with_options(config_set_callback, repo->config, NULL, + repo, &opts) < 0) /* * config_with_options() normally returns only * zero, as most errors are fatal, and @@ -2725,7 +2704,7 @@ static void repo_config_clear(struct repository *repo) void repo_config(struct repository *repo, config_fn_t fn, void *data) { git_config_check_init(repo); - configset_iter(&the_reader, repo->config, fn, data); + configset_iter(repo->config, fn, data); } int repo_config_get(struct repository *repo, const char *key) @@ -2832,19 +2811,17 @@ static void read_protected_config(void) .ignore_worktree = 1, .system_gently = 1, }; - struct configset_add_data data = CONFIGSET_ADD_INIT; git_configset_init(&protected_config); - data.config_set = &protected_config; - data.config_reader = &the_reader; - config_with_options(config_set_callback, &data, NULL, NULL, &opts); + config_with_options(config_set_callback, &protected_config, NULL, + NULL, &opts); } void git_protected_config(config_fn_t fn, void *data) { if (!protected_config.hash_initialized) read_protected_config(); - configset_iter(&the_reader, &protected_config, fn, data); + configset_iter(&protected_config, fn, data); } /* Functions used historically to read configuration from 'the_repository' */ -- cgit v1.3-5-g9baa From 908857a9f8a63c7d8fee1bd5f52b1aa1cf3434de Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:29 +0000 Subject: config: add kvi.path, use it to evaluate includes Include directives are evaluated using the path of the config file. To reduce the dependence on "config_reader.source", add a new "key_value_info.path" member and use that instead of "config_source.path". This allows us to remove a "struct config_reader *" field from "struct config_include_data", which will subsequently allow us to remove "struct config_reader" entirely. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- config.c | 40 +++++++++++++++++++--------------------- config.h | 2 ++ 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 50dbd89a6d..8d342d8425 100644 --- a/config.c +++ b/config.c @@ -162,7 +162,6 @@ struct config_include_data { const struct config_options *opts; struct git_config_source *config_source; struct repository *repo; - struct config_reader *config_reader; /* * All remote URLs discovered when reading all config files. @@ -181,8 +180,7 @@ static const char include_depth_advice[] = N_( "from\n" " %s\n" "This might be due to circular includes."); -static int handle_path_include(struct config_source *cs, - const struct key_value_info *kvi, +static int handle_path_include(const struct key_value_info *kvi, const char *path, struct config_include_data *inc) { @@ -205,14 +203,14 @@ static int handle_path_include(struct config_source *cs, if (!is_absolute_path(path)) { char *slash; - if (!cs || !cs->path) { + if (!kvi || !kvi->path) { ret = error(_("relative config includes must come from files")); goto cleanup; } - slash = find_last_dir_sep(cs->path); + slash = find_last_dir_sep(kvi->path); if (slash) - strbuf_add(&buf, cs->path, slash - cs->path + 1); + strbuf_add(&buf, kvi->path, slash - kvi->path + 1); strbuf_addstr(&buf, path); path = buf.buf; } @@ -220,8 +218,8 @@ static int handle_path_include(struct config_source *cs, if (!access_or_die(path, R_OK, 0)) { if (++inc->depth > MAX_INCLUDE_DEPTH) die(_(include_depth_advice), MAX_INCLUDE_DEPTH, path, - !cs ? "" : - cs->name ? cs->name : + !kvi ? "" : + kvi->filename ? kvi->filename : "the command line"); ret = git_config_from_file_with_options(git_config_include, path, inc, kvi->scope, NULL); @@ -239,7 +237,7 @@ static void add_trailing_starstar_for_dir(struct strbuf *pat) strbuf_addstr(pat, "**"); } -static int prepare_include_condition_pattern(struct config_source *cs, +static int prepare_include_condition_pattern(const struct key_value_info *kvi, struct strbuf *pat) { struct strbuf path = STRBUF_INIT; @@ -256,11 +254,11 @@ static int prepare_include_condition_pattern(struct config_source *cs, if (pat->buf[0] == '.' && is_dir_sep(pat->buf[1])) { const char *slash; - if (!cs || !cs->path) + if (!kvi || !kvi->path) return error(_("relative config include " "conditionals must come from files")); - strbuf_realpath(&path, cs->path, 1); + strbuf_realpath(&path, kvi->path, 1); slash = find_last_dir_sep(path.buf); if (!slash) BUG("how is this possible?"); @@ -275,7 +273,7 @@ static int prepare_include_condition_pattern(struct config_source *cs, return prefix; } -static int include_by_gitdir(struct config_source *cs, +static int include_by_gitdir(const struct key_value_info *kvi, const struct config_options *opts, const char *cond, size_t cond_len, int icase) { @@ -292,7 +290,7 @@ static int include_by_gitdir(struct config_source *cs, strbuf_realpath(&text, git_dir, 1); strbuf_add(&pattern, cond, cond_len); - prefix = prepare_include_condition_pattern(cs, &pattern); + prefix = prepare_include_condition_pattern(kvi, &pattern); again: if (prefix < 0) @@ -428,16 +426,16 @@ static int include_by_remote_url(struct config_include_data *inc, inc->remote_urls); } -static int include_condition_is_true(struct config_source *cs, +static int include_condition_is_true(const struct key_value_info *kvi, struct config_include_data *inc, const char *cond, size_t cond_len) { const struct config_options *opts = inc->opts; if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len)) - return include_by_gitdir(cs, opts, cond, cond_len, 0); + return include_by_gitdir(kvi, opts, cond, cond_len, 0); else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len)) - return include_by_gitdir(cs, opts, cond, cond_len, 1); + return include_by_gitdir(kvi, opts, cond, cond_len, 1); else if (skip_prefix_mem(cond, cond_len, "onbranch:", &cond, &cond_len)) return include_by_branch(cond, cond_len); else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond, @@ -453,7 +451,6 @@ static int git_config_include(const char *var, const char *value, void *data) { struct config_include_data *inc = data; - struct config_source *cs = inc->config_reader->source; const char *cond, *key; size_t cond_len; int ret; @@ -467,16 +464,16 @@ static int git_config_include(const char *var, const char *value, return ret; if (!strcmp(var, "include.path")) - ret = handle_path_include(cs, ctx->kvi, value, inc); + ret = handle_path_include(ctx->kvi, value, inc); if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) && - cond && include_condition_is_true(cs, inc, cond, cond_len) && + cond && include_condition_is_true(ctx->kvi, inc, cond, cond_len) && !strcmp(key, "path")) { config_fn_t old_fn = inc->fn; if (inc->opts->unconditional_remote_url) inc->fn = forbid_remote_url; - ret = handle_path_include(cs, ctx->kvi, value, inc); + ret = handle_path_include(ctx->kvi, value, inc); inc->fn = old_fn; } @@ -661,6 +658,7 @@ void kvi_from_param(struct key_value_info *out) out->linenr = -1; out->origin_type = CONFIG_ORIGIN_CMDLINE; out->scope = CONFIG_SCOPE_COMMAND; + out->path = NULL; } int git_config_parse_parameter(const char *text, @@ -1064,6 +1062,7 @@ static void kvi_from_source(struct config_source *cs, out->origin_type = cs->origin_type; out->linenr = cs->linenr; out->scope = scope; + out->path = cs->path; } static int git_parse_source(struct config_source *cs, config_fn_t fn, @@ -2282,7 +2281,6 @@ int config_with_options(config_fn_t fn, void *data, inc.opts = opts; inc.repo = repo; inc.config_source = config_source; - inc.config_reader = &the_reader; fn = git_config_include; data = &inc; } diff --git a/config.h b/config.h index bd366ddb5e..b5573e67a0 100644 --- a/config.h +++ b/config.h @@ -116,12 +116,14 @@ struct key_value_info { int linenr; enum config_origin_type origin_type; enum config_scope scope; + const char *path; }; #define KVI_INIT { \ .filename = NULL, \ .linenr = -1, \ .origin_type = CONFIG_ORIGIN_UNKNOWN, \ .scope = CONFIG_SCOPE_UNKNOWN, \ + .path = NULL, \ } /* Captures additional information that a config callback can use. */ -- cgit v1.3-5-g9baa From 6e8e7981eb86e2c19401825dbdb55d5860d11313 Mon Sep 17 00:00:00 2001 From: Glen Choo Date: Wed, 28 Jun 2023 19:26:30 +0000 Subject: config: pass source to config_parser_event_fn_t ..so that the callback can use a "struct config_source" parameter instead of "config_reader.source". "struct config_source" is internal to config.c, so we are adding a pointer to a struct defined in config.c into a public function signature defined in config.h, but this is okay because this function has only ever been (and probably ever will be) used internally by config.c. As a result, the_reader isn't used anywhere, so "struct config_reader" is obsolete (it was only intended to be used with the_reader). Remove them. Signed-off-by: Glen Choo Signed-off-by: Junio C Hamano --- config.c | 77 +++++++++++----------------------------------------------------- config.h | 6 +++++ 2 files changed, 19 insertions(+), 64 deletions(-) (limited to 'config.c') diff --git a/config.c b/config.c index 8d342d8425..b3de01239d 100644 --- a/config.c +++ b/config.c @@ -66,40 +66,6 @@ struct config_source { }; #define CONFIG_SOURCE_INIT { 0 } -struct config_reader { - /* - * These members record the "current" config source, which can be - * accessed by parsing callbacks. - * - * The "source" variable will be non-NULL only when we are actually - * parsing a real config source (file, blob, cmdline, etc). - */ - struct config_source *source; -}; -/* - * Where possible, prefer to accept "struct config_reader" as an arg than to use - * "the_reader". "the_reader" should only be used if that is infeasible, e.g. in - * a public function. - */ -static struct config_reader the_reader; - -static inline void config_reader_push_source(struct config_reader *reader, - struct config_source *top) -{ - top->prev = reader->source; - reader->source = top; -} - -static inline struct config_source *config_reader_pop_source(struct config_reader *reader) -{ - struct config_source *ret; - if (!reader->source) - BUG("tried to pop config source, but we weren't reading config"); - ret = reader->source; - reader->source = reader->source->prev; - return ret; -} - static int pack_compression_seen; static int zlib_compression_seen; @@ -752,14 +718,9 @@ int git_config_from_parameters(config_fn_t fn, void *data) struct strvec to_free = STRVEC_INIT; int ret = 0; char *envw = NULL; - struct config_source source = CONFIG_SOURCE_INIT; struct key_value_info kvi = KVI_INIT; - source.origin_type = CONFIG_ORIGIN_CMDLINE; - config_reader_push_source(&the_reader, &source); - kvi_from_param(&kvi); - env = getenv(CONFIG_COUNT_ENVIRONMENT); if (env) { unsigned long count; @@ -816,7 +777,6 @@ out: strbuf_release(&envvar); strvec_clear(&to_free); free(envw); - config_reader_pop_source(&the_reader); return ret; } @@ -1045,7 +1005,7 @@ static int do_event(struct config_source *cs, enum config_event_t type, if (data->previous_type != CONFIG_EVENT_EOF && data->opts->event_fn(data->previous_type, data->previous_offset, - offset, data->opts->event_fn_data) < 0) + offset, cs, data->opts->event_fn_data) < 0) return -1; data->previous_type = type; @@ -2002,8 +1962,7 @@ int git_default_config(const char *var, const char *value, * fgetc, ungetc, ftell of top need to be initialized before calling * this function. */ -static int do_config_from(struct config_reader *reader, - struct config_source *top, config_fn_t fn, +static int do_config_from(struct config_source *top, config_fn_t fn, void *data, enum config_scope scope, const struct config_options *opts) { @@ -2016,21 +1975,17 @@ static int do_config_from(struct config_reader *reader, top->total_len = 0; strbuf_init(&top->value, 1024); strbuf_init(&top->var, 1024); - config_reader_push_source(reader, top); kvi_from_source(top, scope, &kvi); ret = git_parse_source(top, fn, &kvi, data, opts); - /* pop config-file parsing state stack */ strbuf_release(&top->value); strbuf_release(&top->var); - config_reader_pop_source(reader); return ret; } -static int do_config_from_file(struct config_reader *reader, - config_fn_t fn, +static int do_config_from_file(config_fn_t fn, const enum config_origin_type origin_type, const char *name, const char *path, FILE *f, void *data, enum config_scope scope, @@ -2049,7 +2004,7 @@ static int do_config_from_file(struct config_reader *reader, top.do_ftell = config_file_ftell; flockfile(f); - ret = do_config_from(reader, &top, fn, data, scope, opts); + ret = do_config_from(&top, fn, data, scope, opts); funlockfile(f); return ret; } @@ -2057,8 +2012,8 @@ static int do_config_from_file(struct config_reader *reader, static int git_config_from_stdin(config_fn_t fn, void *data, enum config_scope scope) { - return do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_STDIN, "", - NULL, stdin, data, scope, NULL); + return do_config_from_file(fn, CONFIG_ORIGIN_STDIN, "", NULL, stdin, + data, scope, NULL); } int git_config_from_file_with_options(config_fn_t fn, const char *filename, @@ -2072,9 +2027,8 @@ int git_config_from_file_with_options(config_fn_t fn, const char *filename, BUG("filename cannot be NULL"); f = fopen_or_warn(filename, "r"); if (f) { - ret = do_config_from_file(&the_reader, fn, CONFIG_ORIGIN_FILE, - filename, filename, f, data, scope, - opts); + ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename, + filename, f, data, scope, opts); fclose(f); } return ret; @@ -2105,7 +2059,7 @@ int git_config_from_mem(config_fn_t fn, top.do_ungetc = config_buf_ungetc; top.do_ftell = config_buf_ftell; - return do_config_from(&the_reader, &top, fn, data, scope, opts); + return do_config_from(&top, fn, data, scope, opts); } int git_config_from_blob_oid(config_fn_t fn, @@ -2198,8 +2152,7 @@ int git_config_system(void) return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0); } -static int do_git_config_sequence(struct config_reader *reader, - const struct config_options *opts, +static int do_git_config_sequence(const struct config_options *opts, const struct repository *repo, config_fn_t fn, void *data) { @@ -2299,7 +2252,7 @@ int config_with_options(config_fn_t fn, void *data, ret = git_config_from_blob_ref(fn, repo, config_source->blob, data, config_source->scope); } else { - ret = do_git_config_sequence(&the_reader, opts, repo, fn, data); + ret = do_git_config_sequence(opts, repo, fn, data); } if (inc.remote_urls) { @@ -3009,7 +2962,6 @@ void git_die_config(const char *key, const char *err, ...) */ struct config_store_data { - struct config_reader *config_reader; size_t baselen; char *key; int do_not_match; @@ -3055,11 +3007,10 @@ static int matches(const char *key, const char *value, (value && !regexec(store->value_pattern, value, 0, NULL, 0)); } -static int store_aux_event(enum config_event_t type, - size_t begin, size_t end, void *data) +static int store_aux_event(enum config_event_t type, size_t begin, size_t end, + struct config_source *cs, void *data) { struct config_store_data *store = data; - struct config_source *cs = store->config_reader->source; ALLOC_GROW(store->parsed, store->parsed_nr + 1, store->parsed_alloc); store->parsed[store->parsed_nr].begin = begin; @@ -3380,8 +3331,6 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, size_t contents_sz; struct config_store_data store = CONFIG_STORE_INIT; - store.config_reader = &the_reader; - /* parse-key returns negative; flip the sign to feed exit(3) */ ret = 0 - git_config_parse_key(key, &store.key, &store.baselen); if (ret) diff --git a/config.h b/config.h index b5573e67a0..6332d74904 100644 --- a/config.h +++ b/config.h @@ -72,6 +72,7 @@ enum config_event_t { CONFIG_EVENT_ERROR }; +struct config_source; /* * The parser event function (if not NULL) is called with the event type and * the begin/end offsets of the parsed elements. @@ -81,6 +82,7 @@ enum config_event_t { */ typedef int (*config_parser_event_fn_t)(enum config_event_t type, size_t begin_offset, size_t end_offset, + struct config_source *cs, void *event_fn_data); struct config_options { @@ -100,6 +102,10 @@ struct config_options { const char *commondir; const char *git_dir; + /* + * event_fn and event_fn_data are for internal use only. Handles events + * emitted by the config parser. + */ config_parser_event_fn_t event_fn; void *event_fn_data; enum config_error_action { -- cgit v1.3-5-g9baa