config: remove global state from config iteration
cover config: remove global state from config iteration
= Description
This series removes all global state from config iteration, i.e. parsing config and iterating configsets, by passing config metadata as a "struct key_value_info" arg to the "config_fn_t" callbacks. This allows us to get rid of:
* "the_reader" (formerly "cf", "current_parsing_scope", "current_config_kvi"), and the config.c machinery that maintained it. This only needed to be global because it was read by...
* The "current_*" functions that read metadata about the 'current' config value ("current_config_scope", "current_config_name", etc), which are replaced by reading values from the "struct key_value_info" passed to the callbacks.
As a result:
* Config iterating code can be moved to into its own library with few modifications. C.f. libification efforts [1].
* The config iterating code can be safely called in parallel.
* We expose and fix instances where the "current_*" functions were being called outside of config callbacks.
We've had this idea of doing this "config_fn_t" refactor for a long time [2], but we've never attempted it because we wanted to avoid churn. After attempting it, though, I'm quite convinced that this is the right way forward for config, since the lack of global state makes things much easier to reason about. The churn is also quite manageable:
* The vast majority of changes can be handled with cocci.
* The few cases that aren't covered by cocci have obvious fixes.
* The change is simple enough for in-flight topics to perform and conflicts will be caught at build time anyway.
* Anecdotally, we don't change config functions often anyway. This merges cleanly with 'seen' and the result passes CI.
= Patch overview
I've arranged the patches in a way that makes them readable, but is unsuitable for merging, hence the RFC tag. The "Post-RFC cleanups" section describes all the changes I'll make prior to submitting this as non-RFC.
1-5/14 converts the config.c machinery to set and make use of "config_reader.config_kvi" instead of "config_reader.source" and "config_reader.scope", which makes it easier to pass "struct key_value_info" to config callbacks. To minimize churn, I opted to 'de-plumb' "struct config_reader" here instead of plumbing it and removing it later.
6-10/14 actually changes "config_fn_t"'s signature. The earlier patches are minor refactors that make the cocci application + adjustment easier. Post RFC, cocci application + adjustment will be a single patch, but for ease of reading I've kept them separate.
11-14/14 teach the config callbacks to use the "kvi" parameter, replace the now-obsolete "current_*" functions, and remove the now-obsolete "struct config_reader". This requires plumbing "kvi" through some more config.c machinery and fixing a sneaky config.c-like code path in trace2/.
= Post-RFC cleanups
* To make future refactors easier, I'm strongly considering replacing the "struct key_value_info" arg with something more extensible so that we can modify that without changing 100+ function signatures. An alternative would be to replace all of the args to config_fn_t with a single struct, but that would very significantly increase churn because we'd need to touch all the config_fn_t function bodies too.
* Rearrange the cocci patches to avoid breaking CI in the middle of the series.
* Fix style issues (e.g. spacing around "kvi", line wrapping, "{ 0 }" instead of dedicated initializer)
= Alternatives considered
Ævar suggested in [3] that we might be able to do the refactor incrementally by having both the old "config_fn_t" and the new "config_fn_t with kvi", which lets us convert some of config iterating (e.g. configsets) without touching the others (e.g. config parsing). I experimented with that for a bit, and it turned out that doing it all at once is actually less work because we don't have to worry about the case where the same "config_fn_t" is used in both git_config() and git_config_from_file().
Jonathan Tan suggested in [4] that to reduce churn, we might be able to convert many of the config_fn_t-s to the config set API before attempting this refactor. But (hopefully), these patches show that the churn is manageable even without this preparatory step.
[1]
https://lore.kernel.org/git/CAJoAoZ=Cig_kLocxKGax31sU7Xe4==BGzC__Bg2_pr7krNq6MA@mail.gmail.com/
[2]
https://lore.kernel.org/git/CAPc5daV6bdUKS-ExHmpT4Ppy2S832NXoyPw7aOLP7fG=WrBPgg@mail.gmail.com/
[3]
https://lore.kernel.org/git/[email protected]
[4]
https://lore.kernel.org/git/[email protected]/
Glen Choo (14):
config.c: introduce kvi_fn(), use it for configsets config.c: use kvi for CLI config
config: use kvi for config files
config: add kvi.path, use it to evaluate includes
config: pass source to config_parser_event_fn_t
config: inline git_color_default_config
urlmatch.h: use config_fn_t type
(RFC-only) config: add kvi arg to config_fn_t (RFC-only) config: apply cocci to config_fn_t implementations (RFC-only) config: finish config_fn_t refactor
config: remove current_config_(line|name|origin_type)
config: remove current_config_scope()
config: pass kvi to die_bad_number()
config: remove config_reader from configset_add_value
alias.c | 3 +- archive-tar.c | 5 +- archive-zip.c | 1 + builtin/add.c | 5 +- builtin/blame.c | 5 +- builtin/branch.c | 8 +- builtin/cat-file.c | 5 +- builtin/checkout.c | 7 +- builtin/clean.c | 9 +- builtin/clone.c | 10 +- builtin/column.c | 3 +- builtin/commit-graph.c | 3 +- builtin/commit.c | 20 +- builtin/config.c | 59 +- builtin/difftool.c | 5 +- builtin/fetch.c | 12 +- builtin/fsmonitor--daemon.c | 11 +- builtin/grep.c | 12 +- builtin/help.c | 5 +- builtin/index-pack.c | 9 +- builtin/log.c | 12 +- builtin/merge.c | 7 +- builtin/multi-pack-index.c | 1 + builtin/pack-objects.c | 19 +- builtin/patch-id.c | 5 +- builtin/pull.c | 5 +- builtin/push.c | 5 +- builtin/read-tree.c | 5 +- builtin/rebase.c | 5 +- builtin/receive-pack.c | 15 +- builtin/reflog.c | 7 +- builtin/remote.c | 12 +- builtin/repack.c | 5 +- builtin/reset.c | 5 +- builtin/send-pack.c | 5 +- builtin/show-branch.c | 8 +- builtin/stash.c | 5 +- builtin/submodule--helper.c | 3 +- builtin/tag.c | 9 +- builtin/var.c | 5 +- builtin/worktree.c | 5 +- bundle-uri.c | 9 +- color.c | 8 - color.h | 6 +- compat/mingw.c | 3 +- compat/mingw.h | 4 +- config.c | 540 +++++++----------- config.h | 56 +- connect.c | 4 +- .../coccinelle/config_fn_kvi.pending.cocci | 146 +++++ contrib/coccinelle/git_config_number.cocci | 27 + convert.c | 4 +- credential.c | 1 + delta-islands.c | 3 +- diff.c | 19 +- diff.h | 7 +- fetch-pack.c | 5 +- fmt-merge-msg.c | 7 +- fmt-merge-msg.h | 3 +- fsck.c | 11 +- fsck.h | 4 +- git-compat-util.h | 2 + gpg-interface.c | 6 +- grep.c | 7 +- grep.h | 4 +- help.c | 10 +- http.c | 15 +- ident.c | 3 +- ident.h | 4 +- imap-send.c | 7 +- ll-merge.c | 1 + ls-refs.c | 2 +- mailinfo.c | 5 +- notes-utils.c | 3 +- notes.c | 3 +- pager.c | 5 +- pretty.c | 1 + promisor-remote.c | 4 +- remote.c | 7 +- revision.c | 3 +- scalar.c | 3 +- sequencer.c | 28 +- setup.c | 17 +- submodule-config.c | 31 +- submodule-config.h | 3 +- t/helper/test-config.c | 21 +- t/helper/test-userdiff.c | 4 +- trace2.c | 4 +- trace2.h | 3 +- trace2/tr2_cfg.c | 12 +- trace2/tr2_sysenv.c | 3 +- trace2/tr2_tgt.h | 4 +- trace2/tr2_tgt_event.c | 4 +- trace2/tr2_tgt_normal.c | 4 +- trace2/tr2_tgt_perf.c | 4 +- trailer.c | 2 + upload-pack.c | 18 +- urlmatch.c | 7 +- urlmatch.h | 8 +- worktree.c | 2 +- xdiff-interface.c | 5 +- xdiff-interface.h | 5 +- 102 files changed, 855 insertions(+), 641 deletions(-) create mode 100644 contrib/coccinelle/config_fn_kvi.pending.cocci create mode 100644 contrib/coccinelle/git_config_number.cocci
base-commit: 9857273be005833c71e2d16ba48e193113e12276
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1497%2Fchooglen%2Fconfig%2Fno-global-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1497/chooglen/config/no-global-v1
Pull-Request: https://github.com/git/git/pull/1497
Signature · 1 line
gitgitgadget
PATCH 1/14 config.c: introduce kvi_fn(), use it for configsets
From: Glen Choo <[email protected]>
In order to pass "struct key_value_info" to config callbacks in a future commit, we want to make sure that a "struct key_value_info" is available in all code paths that invoke a config callback.
Enforce this by introducing a helper function, "kvi_fn()", that sets "the_reader.config_kvi" before invoking the config callback, and trivially use it in "configset_iter()". This closely simulates passing an extra "struct key_value_info" such that making the switch will be trivial.
This breaks our rule that no underlying machinery uses "the_reader", but "struct config_reader" will be gone by the end of the series so there's no point plumbing it as an arg.
--- config.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
config.c +20 -12
@@ -660,6 +660,17 @@ out_free_ret_1:return -CONFIG_INVALID_KEY ; } +static int kvi_fn (config_fn_t fn,const char *key,const char *value, +struct key_value_info *kvi, +void *data) +{ +int ret; +config_reader_set_kvi (&the_reader, kvi); + ret =fn (key, value, data); +config_reader_set_kvi (&the_reader,NULL ); +return ret; +} +static int config_parse_pair (const char *key,const char *value,config_fn_t fn,void *data) {
@@ -2288,27 +2299,24 @@ 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;struct config_set_element *entry;struct configset_list *list = &set->list; +struct key_value_info *kvi;for (i =0 ; i < list->nr; i++) { entry = list->items[i].e; value_index = list->items[i].value_index; values = &entry->value_list; + kvi = values->items[value_index].util; -config_reader_set_kvi (reader, values->items[value_index].util); - -if (fn (entry->key, values->items[value_index].string, data) <0 ) -git_die_config_linenr (entry->key, - reader->config_kvi->filename, - reader->config_kvi->linenr); - -config_reader_set_kvi (reader,NULL ); +if (kvi_fn (fn, entry->key, values->items[value_index].string, + kvi, data) <0 ) +git_die_config_linenr (entry->key, kvi->filename, + kvi->linenr); } }
@@ -2696,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)
@@ -2815,7 +2823,7 @@ 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' */
Signature · 1 line
gitgitgadget
PATCH 2/14 config.c: use kvi for CLI config
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Plumb "struct key_value_info" and use "kvi_fn()" when parsing CLI config. Do this by refactoring out and reusing the logic that sets the "struct key_value_info" members when caching CLI config in a configset.
This lets us get rid of the fake "struct config_source" in "git_config_from_parameters()", so we now only have to maintain one implementation. Additionally, this plumbing also reveals that "git_config_parse_parameter()" hasn't been setting either "the_reader.source" or "the_reader.config_kvi", so any calls to "current_*" would either BUG() or return *_UNKNOWN values.
Also, get rid of the BUG() checks that forbid setting ".config_kvi" and ".source" at the same time, since we will run afoul of that check. They will soon be unnecessary when we remove ".source".
--- config.c | 58 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-)
config.c +29 -29
@@ -99,8 +99,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; }
@@ -118,16 +116,12 @@ static inline struct config_source *config_reader_pop_source(struct config_readestatic 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; }
@@ -672,7 +666,8 @@ static int kvi_fn(config_fn_t fn, const char *key, const char *value, }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;
@@ -682,17 +677,30 @@ 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 = (kvi_fn (fn, canonical_name, value, kvi, data) <0 ) ?-1 :0 ;free (canonical_name);return ret; } + +/* for values read from `git_config_from_parameters()` */ +static 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 = {0 }; + +kvi_from_param (&kvi); pair =strbuf_split_str (text,'=' ,2 );if (!pair[0 ])
@@ -711,12 +719,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) {
@@ -750,7 +759,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 {
@@ -774,11 +783,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 ; - - source.origin_type =CONFIG_ORIGIN_CMDLINE ; -config_reader_push_source (&the_reader, &source); +struct key_value_info kvi = {0 }; +kvi_from_param (&kvi); env =getenv (CONFIG_COUNT_ENVIRONMENT );if (env) {unsigned long count;
@@ -814,7 +821,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; }
@@ -825,7 +832,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; }
@@ -835,7 +842,6 @@ out:strbuf_release (&envvar);strvec_clear (&to_free);free (envw); -config_reader_pop_source (&the_reader);return ret; }
@@ -2241,7 +2247,7 @@ static int do_git_config_sequence(struct config_reader *reader,free (path); } -config_reader_set_scope (reader,CONFIG_SCOPE_COMMAND ); +config_reader_set_scope (reader,0 );if (!opts->ignore_cmdline &&git_config_from_parameters (fn, data) <0 )die (_ ("unable to parse command-line config" ));
@@ -2423,19 +2429,13 @@ static int configset_add_value(struct config_reader *reader, 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) { +if (reader->source && reader->source->name) { kv_info->filename =strintern (reader->source->name); kv_info->linenr = reader->source->linenr; kv_info->origin_type = reader->source->origin_type; - }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; + }else +kvi_from_param (kv_info); si->util = kv_info;return 0 ;
Signature · 1 line
gitgitgadget
PATCH 6/14 config: inline git_color_default_config
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
git_color_default_config() is a shorthand for calling two other config callbacks. There are no other non-static functions that do this and it will complicate our refactoring of config_fn_t so inline it instead.
--- builtin/branch.c | 5 ++++- builtin/clean.c | 6 ++++-- builtin/grep.c | 5 ++++- builtin/show-branch.c | 5 ++++- builtin/tag.c | 6 +++++- color.c | 8 -------- color.h | 6 +----- 7 files changed, 22 insertions(+), 19 deletions(-)
builtin/branch.c +4 -1
@@ -114,7 +114,10 @@ static int git_branch_config(const char *var, const char *value, void *cb)return 0 ; } -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static const char *branch_get_color (enum color_branch ix)
builtin/clean.c +4 -2
@@ -129,8 +129,10 @@ static int git_clean_config(const char *var, const char *value, void *cb)return 0 ; } -/* inspect the color.ui config variable and others */ -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static const char *clean_get_color (enum color_clean ix)
builtin/grep.c +4 -1
@@ -290,7 +290,10 @@ static int wait_all(void)static int grep_cmd_config (const char *var,const char *value,void *cb) {int st =grep_config (var, value, cb); -if (git_color_default_config (var, value,NULL ) <0 ) + +if (git_color_config (var, value, cb) <0 ) + st =-1 ; +else if (git_default_config (var, value, cb) <0 ) st =-1 ;if (!strcmp (var,"grep.threads" )) {
builtin/show-branch.c +4 -1
@@ -576,7 +576,10 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)return 0 ; } -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static int omit_in_dense (struct commit *commit,struct commit **rev,int n)
builtin/tag.c +5 -1
@@ -204,7 +204,11 @@ static int git_tag_config(const char *var, const char *value, void *cb)if (starts_with (var,"column." ))return git_column_config (var, value,"tag" , &colopts); -return git_color_default_config (var, value, cb); + +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static void write_tag_body (int fd,const struct object_id *oid)
color.c +0 -8
@@ -427,14 +427,6 @@ int git_color_config(const char *var, const char *value, void *cb UNUSED)return 0 ; } -int git_color_default_config (const char *var,const char *value,void *cb) -{ -if (git_color_config (var, value, cb) <0 ) -return -1 ; - -return git_default_config (var, value, cb); -} -void color_print_strbuf (FILE *fp,const char *color,const struct strbuf *sb) {if (*color)
color.h +1 -5
@@ -88,12 +88,8 @@ extern const int column_colors_ansi_max;*/ extern int color_stdout_is_tty; -/* -* Use the first one if you need only color config; the second is a convenience -* if you are just going to change to git_default_config, too. -*/ +/* Parse color config. */ int git_color_config (const char *var,const char *value,void *cb); -int git_color_default_config (const char *var,const char *value,void *cb);/* * Parse a config option, which can be a boolean or one of
Signature · 1 line
gitgitgadget
PATCH 3/14 config: use kvi for config files
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Plumb "struct key_value_info" and use "kvi_fn()" when parsing config files. As a result, "config_reader.kvi" is now always set correctly, so we can remove "config_reader.scope" (but not the ".source" member since that's still needed by some non-parsing machinery). This requires plumbing an additional "enum config_scope" arg through "git_config_from_file_with_options()" and the underlying machinery to make up for the fact that "struct key_value_info" has a ".scope" member, but "struct config_source" does not.
To handle "include" directives correctly, use push/pop semantics for "config_reader.config_kvi" (instead of "set" semantics) like we do for "config_reader.source". Otherwise, "config_reader.config_kvi" won't be set correctly when we finish parsing an included config file and we want to "pop" it to resume parsing the original file. This distinction only matters while there is a global "kvi", i.e. it will be obsolete at the end of the series.
--- bundle-uri.c | 1 + config.c | 171 ++++++++++++++++++++++++--------------------- config.h | 9 ++- fsck.c | 3 +- submodule-config.c | 5 +- 5 files changed, 104 insertions(+), 85 deletions(-)
bundle-uri.c +1 -0
@@ -252,6 +252,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 ) {
config.c +92 -79
425 lines not on this page · raw message
config.h +6 -3
@@ -142,16 +142,18 @@ int git_default_config(const char *, const char *, void *);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);
@@ -672,6 +674,7 @@ struct key_value_info {int linenr;enum config_origin_type origin_type;enum config_scope scope; +struct key_value_info *prev; };/**
fsck.c +2 -1
@@ -1235,7 +1235,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" );
submodule-config.c +3 -2
@@ -603,7 +603,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);
@@ -711,7 +711,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);
Signature · 1 line
gitgitgadget
PATCH 4/14 config: add kvi.path, use it to evaluate includes
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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".
--- config.c | 40 ++++++++++++++++++++-------------------- config.h | 1 + 2 files changed, 21 insertions(+), 20 deletions(-)
config.c +20 -20
@@ -199,7 +199,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 char *path, +static int handle_path_include (struct key_value_info *kvi,const char *path,struct config_include_data *inc) {int ret =0 ;
@@ -221,14 +221,14 @@ static int handle_path_include(struct config_source *cs, const char *path,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; }
@@ -236,12 +236,11 @@ static int handle_path_include(struct config_source *cs, const char *path,if (!access_or_die (path,R_OK ,0 )) {if (++inc->depth >MAX_INCLUDE_DEPTH )die (_ (include_depth_advice),MAX_INCLUDE_DEPTH , path, - !cs ?"<unknown>" : - cs->name ? cs->name : + !kvi ?"<unknown>" : + kvi->filename ? kvi->filename :"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:
@@ -256,7 +255,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 (struct key_value_info *kvi,struct strbuf *pat) {struct strbuf path =STRBUF_INIT ;
@@ -273,11 +272,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?" );
@@ -292,7 +291,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 (struct key_value_info *kvi,const struct config_options *opts,const char *cond,size_t cond_len,int icase) {
@@ -309,7 +308,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 )
@@ -442,16 +441,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 (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,
@@ -467,7 +466,6 @@ static int kvi_fn(config_fn_t fn, const char *key, const char *value,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;struct key_value_info *kvi = inc->config_reader->config_kvi;const char *cond, *key;size_t cond_len;
@@ -482,16 +480,16 @@ static int git_config_include(const char *var, const char *value, void *data)return ret;if (!strcmp (var,"include.path" )) - ret =handle_path_include (cs, value, inc); + ret =handle_path_include (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 (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, value, inc); + ret =handle_path_include (kvi, value, inc); inc->fn = old_fn; }
@@ -683,6 +681,7 @@ static 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,
@@ -1077,6 +1076,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,
config.h +1 -0
@@ -674,6 +674,7 @@ struct key_value_info {int linenr;enum config_origin_type origin_type;enum config_scope scope; +const char *path;struct key_value_info *prev; };
Signature · 1 line
gitgitgadget
PATCH 5/14 config: pass source to config_parser_event_fn_t
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
..so that the callback can use a "struct config_source" parameter instead of "config_reader.source". "struct config_source" is internal to config.c, but this refactor is okay because this function has only ever been (and probably ever will be) used internally by config.c.
This removes the last user of "config_reader.source", so remove it too.
--- config.c | 72 ++++++++++---------------------------------------------- config.h | 6 +++++ 2 files changed, 18 insertions(+), 60 deletions(-)
config.c +12 -60
@@ -60,23 +60,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). -* -* 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; };/*
@@ -86,23 +69,6 @@ struct config_reader {*/ 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 inline void config_reader_push_kvi (struct config_reader *reader,struct key_value_info *kvi) {
@@ -1059,7 +1025,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;
@@ -2020,8 +1986,7 @@ int git_default_config(const char *var, const char *value, void *cb)* 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) {
@@ -2034,21 +1999,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,
@@ -2067,7 +2028,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;
@@ -2076,8 +2037,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,
@@ -2091,9 +2052,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;
@@ -2124,7 +2084,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,
@@ -3019,7 +2979,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;
@@ -3065,11 +3024,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;
@@ -3389,8 +3347,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)
@@ -3951,8 +3907,6 @@ static int reader_origin_type(struct config_reader *reader, {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 ;
@@ -4005,8 +3959,6 @@ 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 ;
@@ -4039,7 +3991,7 @@ int current_config_line(void)if (the_reader.config_kvi)return the_reader.config_kvi->linenr;else -return the_reader.source->linenr; +BUG ("current_config_line called outside config callback" ); }int lookup_config (const char **mapping,int nr_mapping,const char *var)
config.h +6 -0
@@ -73,6 +73,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.
@@ -82,6 +83,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 {
@@ -101,6 +103,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 {
Signature · 1 line
gitgitgadget
PATCH 7/14 urlmatch.h: use config_fn_t type
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
These are actually used as config callbacks, so use the typedef-ed type and make future refactors easier.
--- urlmatch.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
urlmatch.h +3 -2
@@ -2,6 +2,7 @@#define URL_MATCH_H #include "string-list.h" +#include "config.h" struct url_info {/* normalized url on success, must be freed, otherwise NULL */
@@ -48,8 +49,8 @@ struct urlmatch_config {const char *key;void *cb; -int (*collect_fn)(const char *var,const char *value,void *cb); -int (*cascade_fn)(const char *var,const char *value,void *cb); +config_fn_t collect_fn; +config_fn_t cascade_fn;/* * Compare the two matches, the one just discovered and the existing * best match and return a negative value if the found item is to be
Signature · 1 line
gitgitgadget
PATCH 8/14 (RFC-only) config: add kvi arg to config_fn_t
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
..without actually changing any of its implementations. This commit does not build - I've split this out for readability, but post-RFC I will squash this with the rest of the refactor + cocci changes.
--- config.c | 2 +- config.h | 20 +-- .../coccinelle/config_fn_kvi.pending.cocci | 146 ++++++++++++++++++ 3 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 contrib/coccinelle/config_fn_kvi.pending.cocci
config.c +1 -1
@@ -617,7 +617,7 @@ static int kvi_fn(config_fn_t fn, const char *key, const char *value, {int ret;config_reader_push_kvi (&the_reader, kvi); - ret =fn (key, value, data); + ret =fn (key, value, kvi, data);config_reader_pop_kvi (&the_reader);return ret; }
config.h +10 -10
@@ -117,6 +117,15 @@ struct config_options { } error_action; }; +struct key_value_info { +const char *filename; +int linenr; +enum config_origin_type origin_type; +enum config_scope scope; +const char *path; +struct key_value_info *prev; +}; +/** * A config callback function takes three parameters: *
@@ -135,7 +144,7 @@ struct config_options {* A config callback should return 0 for success, or -1 if the variable * could not be parsed properly. */ -typedef int (*config_fn_t )(const char *,const char *,void *); +typedef int (*config_fn_t )(const char *,const char *,struct key_value_info *,void *);int git_default_config (const char *,const char *,void *);
@@ -675,15 +684,6 @@ int git_config_get_expiry(const char *key, const char **output);/* parse either "this many days" integer, or "5.days.ago" approxidate */ int git_config_get_expiry_in_days (const char *key,timestamp_t *,timestamp_t now); -struct key_value_info { -const char *filename; -int linenr; -enum config_origin_type origin_type; -enum config_scope scope; -const char *path; -struct key_value_info *prev; -}; -/** * First prints the error message specified by the caller in `err` and then * dies printing the line number and the file name of the highest priority
contrib/coccinelle/config_fn_kvi.pending.cocci new file +146 -0
146 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH 10/14 (RFC-only) config: finish config_fn_t refactor
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Here's an exhaustive list of all of the changes:
* Cases that need a judgement call
- trace2/tr2_cfg.c:tr2_cfg_set_fl()
This function needs to account for tr2_cfg_cb() now using "kvi". Since this is only called (indirectly) by git_config_set(), config source information has never been available here, so just pass NULL. It will be tr2_cfg_cb()'s responsibility to not use "kvi".
- builtin/checkout.c:checkout_main()
This calls git_xmerge_config() as a shorthand for parsing a CLI arg. "kvi" doesn't apply, so just pass NULL. This might be worth refactoring away, since git_xmerge_config() can call git_default_config().
- config.c:git_config_include()
Replace the local "kvi" variable with the "kvi" parameter. This makes config_include_data.config_reader obsolete, so remove it.
* Hard for cocci to catch
- urlmatch.c
Manually refactor the custom config callbacks in "struct urlmatch_config".
- diff.h, fsck.h, grep.h, ident.h, xdiff-interface.h
"struct key_value_info" hasn't been defined yet, so forward declare it. Alternatively, maybe these files should "#include config.h".
* Likely deficiencies in .cocci patch
- submodule-config.c:gitmodules_cb()
Manually refactor a parse_config() call that gets missed because it uses a different "*data" arg.
- grep.h, various
Manually refactor grep_config() calls. Not sure why these don't get picked up.
- config.c:git_config_include(), http.c:http_options()
Manually add "kvi" where it was missed. Not sure why they get missed.
- builtin/clone.c:write_one_config()
Manually refactor a git_clone_config() call. Probably got missed because I didn't include git_config_parse_parameter().
- ident.h
Remove the UNUSED attribute. Not sure why this is the only instance of this.
- git-compat-util.h, compat/mingw.[h|c]
Manually refactor noop_core_config(), platform_core_config() and mingw_core_config(). I can probably add these as "manual fixups" in cocci.
--- builtin/checkout.c | 2 +- builtin/clone.c | 4 ++-- builtin/grep.c | 2 +- compat/mingw.c | 3 ++- compat/mingw.h | 4 +++- config.c | 5 +---- diff.h | 1 + fsck.h | 1 + git-compat-util.h | 2 ++ grep.c | 6 +++--- grep.h | 4 +++- http.c | 5 +++-- ident.h | 3 ++- submodule-config.c | 4 ++-- trace2/tr2_cfg.c | 2 +- urlmatch.c | 6 +++--- xdiff-interface.h | 2 ++ 17 files changed, 33 insertions(+), 23 deletions(-)
builtin/checkout.c +1 -1
@@ -1687,7 +1687,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,if (opts->conflict_style) { opts->merge =1 ;/* implied */ -git_xmerge_config ("merge.conflictstyle" , opts->conflict_style,NULL ); +git_xmerge_config ("merge.conflictstyle" , opts->conflict_style,NULL ,NULL ); }if (opts->force) { opts->discard_changes =1 ;
builtin/clone.c +2 -2
@@ -791,14 +791,14 @@ static int git_clone_config(const char *k, const char *v, }static int write_one_config (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {/* * give git_clone_config a chance to write config values back to the * environment, since git_config_set_multivar_gently only deals with * config-file writes */ -int apply_failed =git_clone_config (key, value, data); +int apply_failed =git_clone_config (key, value, kvi, data);if (apply_failed)return apply_failed;
builtin/grep.c +1 -1
@@ -290,7 +290,7 @@ static int wait_all(void)static int grep_cmd_config (const char *var,const char *value,struct key_value_info *kvi,void *cb) { -int st =grep_config (var, value, cb); +int st =grep_config (var, value, kvi, cb);if (git_color_config (var, value, cb) <0 ) st =-1 ;
compat/mingw.c +2 -1
@@ -242,7 +242,8 @@ static int core_restrict_inherited_handles = -1;static enum hide_dotfiles_type hide_dotfiles =HIDE_DOTFILES_DOTGITONLY ;static char *unset_environment_variables; -int mingw_core_config (const char *var,const char *value,void *cb) +int mingw_core_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {if (!strcmp (var,"core.hidedotfiles" )) {if (value && !strcasecmp (value,"dotgitonly" ))
compat/mingw.h +3 -1
@@ -11,7 +11,9 @@ typedef _sigset_t sigset_t;#undef _POSIX_THREAD_SAFE_FUNCTIONS#endif -int mingw_core_config (const char *var,const char *value,void *cb); +struct key_value_info ; +int mingw_core_config (const char *var,const char *value, +struct key_value_info *,void *cb);#define platform_core_config mingw_core_config/*
config.c +1 -4
@@ -147,7 +147,6 @@ struct config_include_data {void *data;const struct config_options *opts;struct git_config_source *config_source; -struct config_reader *config_reader;/* * All remote URLs discovered when reading all config files.
@@ -433,10 +432,9 @@ static int include_condition_is_true(struct key_value_info *kvi,static int kvi_fn (config_fn_t fn,const char *key,const char *value,struct key_value_info *kvi,void *data);static int git_config_include (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {struct config_include_data *inc = data; -struct key_value_info *kvi = inc->config_reader->config_kvi;const char *cond, *key;size_t cond_len;int ret;
@@ -2252,7 +2250,6 @@ int config_with_options(config_fn_t fn, void *data, inc.data = data; inc.opts = opts; inc.config_source = config_source; - inc.config_reader = &the_reader; fn = git_config_include; data = &inc; }
diff.h +1 -0
@@ -532,6 +532,7 @@ void free_diffstat_info(struct diffstat_t *diffstat);int parse_long_opt (const char *opt,const char **argv,const char **optarg); +struct key_value_info ;int git_diff_basic_config (const char *var,const char *value,struct key_value_info *kvi,void *cb);int git_diff_heuristic_config (const char *var,const char *value,void *cb);
fsck.h +1 -0
@@ -233,6 +233,7 @@ void fsck_put_object_name(struct fsck_options *options,const char *fsck_describe_object (struct fsck_options *options,const struct object_id *oid); +struct key_value_info ;/* * git_config() callback for use by fsck-y tools that want to support * fsck.<msg> fsck.skipList etc.
git-compat-util.h +2 -0
@@ -440,8 +440,10 @@ typedef uintmax_t timestamp_t;#endif #ifndef platform_core_config +struct key_value_info ; static inline int noop_core_config(const char *var UNUSED, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {return 0 ;
grep.c +3 -3
@@ -55,7 +55,7 @@ define_list_config_array_extra(color_grep_slots, {"match"});* the grep_defaults template. */ int grep_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct grep_opt *opt = cb;const char *slot;
@@ -90,9 +90,9 @@ int grep_config(const char *var, const char *value,if (!strcmp (var,"color.grep" )) opt->color =git_config_colorbool (var, value);if (!strcmp (var,"color.grep.match" )) { -if (grep_config ("color.grep.matchcontext" , value, cb) <0 ) +if (grep_config ("color.grep.matchcontext" , value, kvi, cb) <0 )return -1 ; -if (grep_config ("color.grep.matchselected" , value, cb) <0 ) +if (grep_config ("color.grep.matchselected" , value, kvi, cb) <0 )return -1 ; }else if (skip_prefix (var,"color.grep." , &slot)) {int i =LOOKUP_CONFIG (color_grep_slots, slot);
grep.h +3 -1
@@ -202,7 +202,9 @@ struct grep_opt { .output = std_output, \ } -int grep_config (const char *var,const char *value,void *); +struct key_value_info ; +int grep_config (const char *var,const char *value,struct key_value_info *kvi, +void *);void grep_init (struct grep_opt *,struct repository *repo);void append_grep_pat (struct grep_opt *opt,const char *pat,size_t patlen,const char *origin,int no,enum grep_pat_token t);
http.c +3 -2
@@ -361,7 +361,8 @@ static void process_curl_messages(void) } } -static int http_options (const char *var,const char *value,void *cb) +static int http_options (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp ("http.version" , var)) {return git_config_string (&curl_http_version, var, value);
@@ -532,7 +533,7 @@ static int http_options(const char *var, const char *value, void *cb) }/* Fall back on the default ones */ -return git_default_config (var, value, cb); +return git_default_config (var, value, kvi, cb); }static int curl_empty_auth_enabled (void )
ident.h +2 -1
@@ -62,7 +62,8 @@ const char *fmt_name(enum want_ident);int committer_ident_sufficiently_given (void );int author_ident_sufficiently_given (void ); +struct key_value_info ;int git_ident_config (const char *,const char *, -struct key_value_info *UNUSED ,void *); +struct key_value_info *,void *);#endif
submodule-config.c +2 -2
@@ -675,7 +675,7 @@ out: }static int gitmodules_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {struct repository *repo = data;struct parse_config_parameter parameter;
@@ -685,7 +685,7 @@ static int gitmodules_cb(const char *var, const char *value, parameter.gitmodules_oid =null_oid (); parameter.overwrite =1 ; -return parse_config (var, value, ¶meter); +return parse_config (var, value, kvi, ¶meter); }void repo_read_gitmodules (struct repository *repo,int skip_if_read)
trace2/tr2_cfg.c +1 -1
@@ -146,5 +146,5 @@ void tr2_cfg_set_fl(const char *file, int line, const char *key,struct tr2_cfg_data data = { file, line };if (tr2_cfg_load_patterns () >0 ) -tr2_cfg_cb (key, value, &data); +tr2_cfg_cb (key, value,NULL , &data); }
urlmatch.c +3 -3
@@ -552,7 +552,7 @@ static int cmp_matches(const struct urlmatch_item *a, }int urlmatch_config_entry (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct string_list_item *item;struct urlmatch_config *collect = cb;
@@ -566,7 +566,7 @@ int urlmatch_config_entry(const char *var, const char *value,if (!skip_prefix (var, collect->section, &key) || *(key++) !='.' ) {if (collect->cascade_fn) -return collect->cascade_fn (var, value, cb); +return collect->cascade_fn (var, value, kvi, cb);return 0 ;/* not interested */ } dot =strrchr (key,'.' );
@@ -610,7 +610,7 @@ int urlmatch_config_entry(const char *var, const char *value,strbuf_addstr (&synthkey, collect->section);strbuf_addch (&synthkey,'.' );strbuf_addstr (&synthkey, key); - retval = collect->collect_fn (synthkey.buf, value, collect->cb); + retval = collect->collect_fn (synthkey.buf, value, kvi, collect->cb);strbuf_release (&synthkey);return retval;
xdiff-interface.h +2 -0
@@ -50,6 +50,8 @@ int buffer_is_binary(const char *ptr, unsigned long size);void xdiff_set_find_func (xdemitconf_t *xecfg,const char *line,int cflags);void xdiff_clear_find_func (xdemitconf_t *xecfg); + +struct key_value_info ;int git_xmerge_config (const char *var,const char *value,struct key_value_info *kvi,void *cb);extern int git_xmerge_style;
Signature · 1 line
gitgitgadget
PATCH 11/14 config: remove current_config_(line|name|origin_type)
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Trivially replace current_config_(line|name|origin_type) by reading the corresponding values from "struct key_value_info". This includes some light "kvi" plumbing for builtin/config.c, and for *origin_type, splitting out a function that turns "enum config_origin_type" into the human-readable string that callbacks actually want.
--- builtin/config.c | 25 +++++++++++++------------ builtin/remote.c | 6 +++--- config.c | 23 +---------------------- config.h | 4 +--- t/helper/test-config.c | 8 ++++---- 5 files changed, 22 insertions(+), 44 deletions(-)
builtin/config.c +13 -12
@@ -191,16 +191,16 @@ 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 (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); }
@@ -214,14 +214,14 @@ static void show_config_scope(struct strbuf *buf) }static int show_all_config (const char *key_,const char *value_, - struct key_value_info *kvi UNUSED, void *cb UNUSED) + struct key_value_info *kvi, void *cb UNUSED) {if (show_origin || show_scope) {struct strbuf buf =STRBUF_INIT ;if (show_scope)show_config_scope (&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);
@@ -239,12 +239,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_, +struct key_value_info *kvi) {if (show_scope)show_config_scope (buf);if (show_origin) -show_config_origin (buf); +show_config_origin (kvi, buf);if (show_keys)strbuf_addstr (buf, key_);if (!omit_values) {
@@ -299,7 +300,7 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value }static int collect_config (const char *key_,const char *value_, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct strbuf_list *values = cb;
@@ -316,7 +317,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)
@@ -381,7 +382,7 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)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,NULL ) <0 )die (_ ("failed to format default config value: %s" ), default_value); }
@@ -618,7 +619,7 @@ 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,NULL );fwrite (buf.buf,1 , buf.len, stdout);strbuf_release (&buf);
builtin/remote.c +3 -3
@@ -646,7 +646,7 @@ struct push_default_info };static int config_read_push_default (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct push_default_info * info = cb; if (strcmp(key, "remote.pushdefault") ||
@@ -655,8 +655,8 @@ static int config_read_push_default(const char *key, const char *value, info->scope =current_config_scope ();strbuf_reset (&info->origin); -strbuf_addstr (&info->origin,current_config_name ()); - info->linenr =current_config_line (); +strbuf_addstr (&info->origin, kvi->filename); + info->linenr = kvi->linenr;return 0 ; }
config.c +1 -22
@@ -3917,13 +3917,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" ;
@@ -3969,14 +3964,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)
@@ -3991,14 +3978,6 @@ enum config_scope current_config_scope(void)return CONFIG_SCOPE_UNKNOWN ; } -int current_config_line (void ) -{ -if (the_reader.config_kvi) -return the_reader.config_kvi->linenr; -else -BUG ("current_config_line called outside config callback" ); -} -int lookup_config (const char **mapping,int nr_mapping,const char *var) {int i;
config.h +1 -3
@@ -375,9 +375,7 @@ 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 ); -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:
t/helper/test-config.c +4 -4
@@ -43,7 +43,7 @@*/ static int iterate_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data UNUSED) + struct key_value_info *kvi, void *data UNUSED) {static int nr;
@@ -52,9 +52,9 @@ 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 ("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 (current_config_scope ()));return 0 ;
Signature · 1 line
gitgitgadget
PATCH 14/14 config: remove config_reader from configset_add_value
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Since we now get "kvi" from the config callback, we can stop passing it via "*data". Now "struct config_reader" has no more references, so get rid of it.
--- config.c | 81 ++++++++++---------------------------------------------- 1 file changed, 14 insertions(+), 67 deletions(-)
config.c +14 -67
@@ -59,33 +59,6 @@ struct config_source { };#define CONFIG_SOURCE_INIT { 0 } -struct config_reader { -struct key_value_info *config_kvi; -}; -/* -* 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_kvi (struct config_reader *reader, -struct key_value_info *kvi) -{ - kvi->prev = reader->config_kvi; - reader->config_kvi = kvi; -} - -static inline struct key_value_info *config_reader_pop_kvi (struct config_reader *reader) -{ -struct key_value_info *ret; -if (!reader->config_kvi) -BUG ("tried to pop config_kvi, but we weren't reading config" ); - ret = reader->config_kvi; - reader->config_kvi = reader->config_kvi->prev; -return ret; -} -static int pack_compression_seen;static int zlib_compression_seen;
@@ -429,8 +402,6 @@ static int include_condition_is_true(struct key_value_info *kvi,return 0 ; } -static int kvi_fn (config_fn_t fn,const char *key,const char *value, -struct key_value_info *kvi,void *data);static int git_config_include (const char *var,const char *value,struct key_value_info *kvi,void *data) {
@@ -443,7 +414,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 =kvi_fn (inc->fn, var, value, kvi, inc->data); + ret = inc->fn (var, value, kvi, inc->data);if (ret <0 )return ret;
@@ -614,16 +585,6 @@ out_free_ret_1:return -CONFIG_INVALID_KEY ; } -static int kvi_fn (config_fn_t fn,const char *key,const char *value, -struct key_value_info *kvi,void *data) -{ -int ret; -config_reader_push_kvi (&the_reader, kvi); - ret =fn (key, value, kvi, data); -config_reader_pop_kvi (&the_reader); -return ret; -} -static int config_parse_pair (const char *key,const char *value,struct key_value_info *kvi,config_fn_t fn,void *data)
@@ -636,7 +597,7 @@ static int config_parse_pair(const char *key, const char *value,if (git_config_parse_key (key, &canonical_name,NULL ))return -1 ; - ret = (kvi_fn (fn, canonical_name, value, kvi, data) <0 ) ?-1 :0 ; + ret = (fn (canonical_name, value, kvi, data) <0 ) ?-1 :0 ;free (canonical_name);return ret; }
@@ -937,7 +898,7 @@ static int get_value(struct config_source *cs, struct key_value_info *kvi,*/ cs->linenr--; kvi->linenr = cs->linenr; - ret =kvi_fn (fn, name->buf, value, kvi, data); + ret =fn (name->buf, value, kvi, data);if (ret >=0 ) cs->linenr++;return ret;
@@ -2289,8 +2250,8 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data) values = &entry->value_list; kvi = values->items[value_index].util; -if (kvi_fn (fn, entry->key, values->items[value_index].string, - kvi, data) <0 ) +if (fn (entry->key, values->items[value_index].string, kvi, + data) <0 )git_die_config_linenr (entry->key, kvi->filename, kvi->linenr); }
@@ -2368,9 +2329,8 @@ static int configset_find_element(struct config_set *set, const char *key,return 0 ; } -static int configset_add_value (struct config_reader *reader, -struct config_set *set,const char *key, -const char *value) +static int configset_add_value (struct config_set *set,const char *key, +const char *value,struct key_value_info *kvi_p) {struct config_set_element *e;struct string_list_item *si;
@@ -2399,7 +2359,7 @@ static int configset_add_value(struct config_reader *reader, l_item->e = e; l_item->value_index = e->value_list.nr -1 ; -memcpy (kv_info, reader->config_kvi,sizeof (struct key_value_info )); +memcpy (kv_info, kvi_p,sizeof (struct key_value_info )); si->util = kv_info;return 0 ;
@@ -2447,26 +2407,19 @@ 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, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) { -struct configset_add_data *data = cb; -configset_add_value (data->config_reader, data->config_set, key, value); +struct config_set *set = cb; +configset_add_value (set, key, value, kvi);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,
@@ -2632,7 +2585,6 @@ int git_configset_get_pathname(struct config_set *set, const char *key, const chstatic 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;
@@ -2644,10 +2596,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 , &opts) <0 ) +if (config_with_options (config_set_callback, repo->config,NULL , &opts) <0 )/* * config_with_options() normally returns only * zero, as most errors are fatal, and
@@ -2786,12 +2736,9 @@ 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 , &opts); +config_with_options (config_set_callback, &protected_config,NULL , &opts); }void git_protected_config (config_fn_t fn,void *data)
Signature · 1 line
gitgitgadget
PATCH 12/14 config: remove current_config_scope()
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Replace current_config_scope() by reading the corresponding value off "struct key_value_info".
Most instances of this are trivial, except for the trace2/* files. 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".
- 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 already used internally by config.c for CLI/environment variable-based config.
--- builtin/config.c | 8 ++++---- builtin/remote.c | 2 +- config.c | 16 +--------------- config.h | 3 ++- remote.c | 6 +++--- t/helper/test-config.c | 2 +- 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 ++-- 13 files changed, 31 insertions(+), 38 deletions(-)
builtin/config.c +4 -4
@@ -204,10 +204,10 @@ static void show_config_origin(struct key_value_info *kvi, struct strbuf *buf)strbuf_addch (buf, term); } -static void show_config_scope (struct strbuf *buf) +static void show_config_scope (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);
@@ -219,7 +219,7 @@ static int show_all_config(const char *key_, const char *value_,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 (kvi, &buf);/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
@@ -243,7 +243,7 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value struct key_value_info *kvi) {if (show_scope) -show_config_scope (buf); +show_config_scope (kvi, buf);if (show_origin)show_config_origin (kvi, buf);if (show_keys)
builtin/remote.c +1 -1
@@ -653,7 +653,7 @@ static int config_read_push_default(const char *key, const char *value, !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, kvi->filename); info->linenr = kvi->linenr;
config.c +1 -15
@@ -643,7 +643,7 @@ static int config_parse_pair(const char *key, const char *value,/* for values read from `git_config_from_parameters()` */ -static void kvi_from_param (struct key_value_info *out) +void kvi_from_param (struct key_value_info *out) { out->filename =NULL ; out->linenr =-1 ;
@@ -3964,20 +3964,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 -/* -* FIXME This should be a BUG, but tr2_list_env_vars_fl is -* calling this outside of a config callback. This will be -* easier to fix when we plumb kvi through the config callbacks, -* so leave this untouched for now. -*/ -return CONFIG_SCOPE_UNKNOWN ; -} -int lookup_config (const char **mapping,int nr_mapping,const char *var) {int i;
config.h +2 -1
@@ -374,7 +374,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);/*
@@ -702,4 +701,6 @@ NORETURN void git_die_config_linenr(const char *key, const char *filename, int l lookup_config(mapping, ARRAY_SIZE(mapping), var)int lookup_config (const char **mapping,int nr_mapping,const char *var); +void kvi_from_param (struct key_value_info *out); +#endif /* CONFIG_H */
remote.c +3 -3
@@ -349,7 +349,7 @@ static void read_branches_file(struct remote_state *remote_state, }static int handle_config (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {const char *name;size_t namelen;
@@ -414,8 +414,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);
t/helper/test-config.c +1 -1
@@ -55,7 +55,7 @@ static int iterate_cb(const char *var, const char *value,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 (current_config_scope ())); +printf ("scope=%s\n" ,config_scope_name (kvi->scope));return 0 ; }
trace2.c +2 -2
@@ -632,7 +632,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,struct key_value_info *kvi) {struct tr2_tgt *tgt_j;int j;
@@ -642,7 +642,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)
trace2.h +2 -1
@@ -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,struct key_value_info *kvi);#define trace2_def_param (param, value) \ trace2_def_param_fl(__FILE__, __LINE__, (param), (value))
trace2/tr2_cfg.c +6 -3
@@ -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, - struct key_value_info *kvi UNUSED, void *d) +struct key_value_info *kvi,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, + 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 = {0 };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); } }
trace2/tr2_tgt.h +3 -1
@@ -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, +struct key_value_info *kvi);typedef void (tr2_tgt_evt_repo_fl_t )(const char *file,int line,const struct repository *repo);
trace2/tr2_tgt_event.c +2 -2
@@ -476,11 +476,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,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 );
trace2/tr2_tgt_normal.c +2 -2
@@ -296,10 +296,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,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,
trace2/tr2_tgt_perf.c +2 -2
@@ -438,12 +438,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,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);
Signature · 1 line
gitgitgadget
PATCH 9/14 (RFC-only) config: apply cocci to config_fn_t implementations
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Pass "struct key_value_info" to *most* functions that are invoked as "config_fn_t" callbacks by applying contrib/coccinelle/config_fn_kvi.pending.cocci. None of the functions actually use the "kvi" arg yet (besides propagating it to a function that now expects "kvi"), but this will be addressed in a later commit. When deciding whether or not to propagate "kvi" to an inner function, only propagate the "kvi" arg if the inner function is actually invoked elsewhere as a config callback; it does not matter whether the function happens have the same signature as config_fn_t.
This commit does not build and has several style issues (e.g. a lack of spacing around the "kvi" arg), but I've split this out for the RFC so that it's more obvious which changes are automatic vs manual. Post-RFC I will squash this with the rest of the refactor + cocci changes.
--- alias.c | 3 ++- archive-tar.c | 3 ++- archive-zip.c | 1 + builtin/add.c | 5 +++-- builtin/blame.c | 5 +++-- builtin/branch.c | 5 +++-- builtin/cat-file.c | 5 +++-- builtin/checkout.c | 5 +++-- builtin/clean.c | 5 +++-- builtin/clone.c | 8 +++++--- builtin/column.c | 3 ++- builtin/commit-graph.c | 1 + builtin/commit.c | 10 ++++++---- builtin/config.c | 10 +++++++--- builtin/difftool.c | 5 +++-- builtin/fetch.c | 8 +++++--- builtin/fsmonitor--daemon.c | 5 +++-- builtin/grep.c | 5 +++-- builtin/help.c | 5 +++-- builtin/index-pack.c | 5 +++-- builtin/log.c | 10 ++++++---- builtin/merge.c | 7 ++++--- builtin/multi-pack-index.c | 1 + builtin/pack-objects.c | 5 +++-- builtin/patch-id.c | 5 +++-- builtin/pull.c | 5 +++-- builtin/push.c | 5 +++-- builtin/read-tree.c | 5 +++-- builtin/rebase.c | 5 +++-- builtin/receive-pack.c | 5 +++-- builtin/reflog.c | 7 ++++--- builtin/remote.c | 6 ++++-- builtin/repack.c | 5 +++-- builtin/reset.c | 5 +++-- builtin/send-pack.c | 5 +++-- builtin/show-branch.c | 5 +++-- builtin/stash.c | 5 +++-- builtin/submodule--helper.c | 1 + builtin/tag.c | 5 +++-- builtin/var.c | 5 +++-- builtin/worktree.c | 5 +++-- bundle-uri.c | 8 ++++++-- config.c | 28 ++++++++++++++++++---------- config.h | 3 ++- connect.c | 4 ++-- convert.c | 4 +++- credential.c | 1 + delta-islands.c | 3 ++- diff.c | 10 ++++++---- diff.h | 6 ++++-- fetch-pack.c | 5 +++-- fmt-merge-msg.c | 5 +++-- fmt-merge-msg.h | 3 ++- fsck.c | 8 +++++--- fsck.h | 3 ++- gpg-interface.c | 6 ++++-- grep.c | 3 ++- help.c | 7 +++++-- ident.c | 3 ++- ident.h | 3 ++- imap-send.c | 5 +++-- ll-merge.c | 1 + ls-refs.c | 2 +- mailinfo.c | 5 +++-- notes-utils.c | 3 ++- notes.c | 3 ++- pager.c | 5 ++++- pretty.c | 1 + promisor-remote.c | 4 +++- remote.c | 3 ++- revision.c | 3 ++- scalar.c | 3 ++- sequencer.c | 8 +++++--- setup.c | 15 ++++++++++----- submodule-config.c | 15 +++++++++++---- t/helper/test-config.c | 9 ++++++--- t/helper/test-userdiff.c | 4 +++- trace2/tr2_cfg.c | 3 ++- trace2/tr2_sysenv.c | 3 ++- trailer.c | 2 ++ upload-pack.c | 8 ++++++-- urlmatch.c | 3 ++- urlmatch.h | 3 ++- xdiff-interface.c | 5 +++-- xdiff-interface.h | 3 ++- 85 files changed, 285 insertions(+), 156 deletions(-)
alias.c +2 -1
@@ -11,7 +11,8 @@ struct config_alias_data {struct string_list *list; }; -static int config_alias_cb (const char *key,const char *value,void *d) +static int config_alias_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct config_alias_data *data = d;const char *p;
archive-tar.c +2 -1
@@ -410,7 +410,8 @@ static int tar_filter_config(const char *var, const char *value,return 0 ; } -static int git_tar_config (const char *var,const char *value,void *cb) +static int git_tar_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {if (!strcmp (var,"tar.umask" )) {if (value && !strcmp (value,"user" )) {
archive-zip.c +1 -0
@@ -616,6 +616,7 @@ static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time) }static int archive_zip_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {return userdiff_config (var, value);
builtin/add.c +3 -2
@@ -355,7 +355,8 @@ static struct option builtin_add_options[] = { OPT_END(), }; -static int add_config (const char *var,const char *value,void *cb) +static int add_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"add.ignoreerrors" ) || !strcmp (var,"add.ignore-errors" )) {
@@ -363,7 +364,7 @@ static int add_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } static const char embedded_advice[] = N_(
builtin/blame.c +3 -2
@@ -692,7 +692,8 @@ static const char *add_prefix(const char *prefix, const char *path)return prefix_path (prefix, prefix ?strlen (prefix) :0 , path); } -static int git_blame_config (const char *var,const char *value,void *cb) +static int git_blame_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"blame.showroot" )) { show_root =git_config_bool (var, value);
@@ -765,7 +766,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)if (userdiff_config (var, value) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int blame_copy_callback (const struct option *option,const char *arg,int unset)
builtin/branch.c +3 -2
@@ -80,7 +80,8 @@ static unsigned int colopts;define_list_config_array (color_branch_slots); -static int git_branch_config (const char *var,const char *value,void *cb) +static int git_branch_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -117,7 +118,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static const char *branch_get_color (enum color_branch ix)
builtin/cat-file.c +3 -2
@@ -882,12 +882,13 @@ static int batch_objects(struct batch_options *opt)return retval; } -static int git_cat_file_config (const char *var,const char *value,void *cb) +static int git_cat_file_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (userdiff_config (var, value) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } static int batch_option_callback(const struct option *opt,
builtin/checkout.c +3 -2
@@ -1182,7 +1182,8 @@ static int switch_branches(const struct checkout_opts *opts,return ret || writeout_error; } -static int git_checkout_config (const char *var,const char *value,void *cb) +static int git_checkout_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct checkout_opts *opts = cb;
@@ -1198,7 +1199,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)if (starts_with (var,"submodule." ))return git_default_submodule_config (var, value,NULL ); -return git_xmerge_config (var, value,NULL ); +return git_xmerge_config (var, value,kvi,NULL ); } static void setup_new_branch_info_and_source_tree(
builtin/clean.c +3 -2
@@ -102,7 +102,8 @@ struct menu_stuff {define_list_config_array (color_interactive_slots); -static int git_clean_config (const char *var,const char *value,void *cb) +static int git_clean_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -132,7 +133,7 @@ static int git_clean_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static const char *clean_get_color (enum color_clean ix)
builtin/clone.c +5 -3
@@ -775,7 +775,8 @@ static int checkout(int submodule_progress, int filter_submodules)return err; } -static int git_clone_config (const char *k,const char *v,void *cb) +static int git_clone_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"clone.defaultremotename" )) {free (remote_name);
@@ -786,10 +787,11 @@ static int git_clone_config(const char *k, const char *v, void *cb)if (!strcmp (k,"clone.filtersubmodules" )) config_filter_submodules =git_config_bool (k, v); -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); } -static int write_one_config (const char *key,const char *value,void *data) +static int write_one_config (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {/* * give git_clone_config a chance to write config values back to the
builtin/column.c +2 -1
@@ -13,7 +13,8 @@ static const char * const builtin_column_usage[] = { };static unsigned int colopts; -static int column_config (const char *var,const char *value,void *cb) +static int column_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {return git_column_config (var, value, cb, &colopts); }
builtin/commit-graph.c +1 -0
@@ -185,6 +185,7 @@ static int write_option_max_new_filters(const struct option *opt, }static int git_commit_graph_write_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var,"commitgraph.maxnewfilters" ))
builtin/commit.c +6 -4
@@ -1402,7 +1402,8 @@ static int parse_status_slot(const char *slot)return LOOKUP_CONFIG (color_status_slots, slot); } -static int git_status_config (const char *k,const char *v,void *cb) +static int git_status_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct wt_status *s = cb;const char *slot_name;
@@ -1487,7 +1488,7 @@ static int git_status_config(const char *k, const char *v, void *cb) s->detect_rename =git_config_rename (k, v);return 0 ; } -return git_diff_ui_config (k, v,NULL ); +return git_diff_ui_config (k, v,kvi,NULL ); }int cmd_status (int argc,const char **argv,const char *prefix)
@@ -1602,7 +1603,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)return 0 ; } -static int git_commit_config (const char *k,const char *v,void *cb) +static int git_commit_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct wt_status *s = cb;
@@ -1624,7 +1626,7 @@ static int git_commit_config(const char *k, const char *v, void *cb)return 0 ; } -return git_status_config (k, v, s); +return git_status_config (k, v,kvi, s); }int cmd_commit (int argc,const char **argv,const char *prefix)
builtin/config.c +7 -3
@@ -214,7 +214,7 @@ static void show_config_scope(struct strbuf *buf) }static int show_all_config (const char *key_,const char *value_, - void *cb UNUSED) + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (show_origin || show_scope) {struct strbuf buf =STRBUF_INIT ;
@@ -298,7 +298,8 @@ static int format_config(struct strbuf *buf, const char *key_, const char *valuereturn 0 ; } -static int collect_config (const char *key_,const char *value_,void *cb) +static int collect_config (const char *key_,const char *value_, + struct key_value_info *kvi UNUSED, void *cb) {struct strbuf_list *values = cb;
@@ -466,6 +467,7 @@ static const char *get_colorbool_slot;static char parsed_color[COLOR_MAXLEN ];static int git_get_color_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var, get_color_slot)) {
@@ -498,6 +500,7 @@ static int get_colorbool_found;static int get_diff_color_found;static int get_color_ui_found;static int git_get_colorbool_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var, get_colorbool_slot))
@@ -555,7 +558,8 @@ struct urlmatch_current_candidate_value {struct strbuf value; }; -static int urlmatch_collect_fn (const char *var,const char *value,void *cb) +static int urlmatch_collect_fn (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct string_list *values = cb;struct string_list_item *item =string_list_insert (values, var);
builtin/difftool.c +3 -2
@@ -38,14 +38,15 @@ static const char *const builtin_difftool_usage[] = { NULL }; -static int difftool_config (const char *var,const char *value,void *cb) +static int difftool_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"difftool.trustexitcode" )) { trust_exit_code =git_config_bool (var, value);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int print_tool_help (void )
builtin/fetch.c +5 -3
@@ -100,7 +100,8 @@ static int fetch_write_commit_graph = -1;static int stdin_refspecs =0 ;static int negotiate_only; -static int git_fetch_config (const char *k,const char *v,void *cb) +static int git_fetch_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"fetch.prune" )) { fetch_prune_config =git_config_bool (k, v);
@@ -140,7 +141,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb)return 0 ; } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }static int parse_refmap_arg (const struct option *opt,const char *arg,int unset)
@@ -1828,7 +1829,8 @@ struct remote_group_data {struct string_list *list; }; -static int get_remote_group (const char *key,const char *value,void *priv) +static int get_remote_group (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *priv) {struct remote_group_data *g = priv;
builtin/fsmonitor--daemon.c +3 -2
@@ -36,7 +36,8 @@ static int fsmonitor__start_timeout_sec = 60;#define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup"static int fsmonitor__announce_startup =0 ; -static int fsmonitor_config (const char *var,const char *value,void *cb) +static int fsmonitor_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,FSMONITOR__IPC_THREADS )) {int i =git_config_int (var, value);
@@ -66,7 +67,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
builtin/grep.c +3 -2
@@ -287,13 +287,14 @@ static int wait_all(void)return hit; } -static int grep_cmd_config (const char *var,const char *value,void *cb) +static int grep_cmd_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {int st =grep_config (var, value, cb);if (git_color_config (var, value, cb) <0 ) st =-1 ; -else if (git_default_config (var, value, cb) <0 ) +else if (git_default_config (var, value,kvi, cb) <0 ) st =-1 ;if (!strcmp (var,"grep.threads" )) {
builtin/help.c +3 -2
@@ -396,7 +396,8 @@ static int add_man_viewer_info(const char *var, const char *value)return 0 ; } -static int git_help_config (const char *var,const char *value,void *cb) +static int git_help_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"help.format" )) {if (!value)
@@ -419,7 +420,7 @@ static int git_help_config(const char *var, const char *value, void *cb)if (starts_with (var,"man." ))return add_man_viewer_info (var, value); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static struct cmdnames main_cmds, other_cmds;
builtin/index-pack.c +3 -2
@@ -1578,7 +1578,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name,strbuf_release (&pack_name); } -static int git_index_pack_config (const char *k,const char *v,void *cb) +static int git_index_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct pack_idx_option *opts = cb;
@@ -1605,7 +1606,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)else opts->flags &= ~WRITE_REV ; } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }static int cmp_uint32 (const void *a_,const void *b_)
builtin/log.c +6 -4
@@ -559,7 +559,8 @@ static int cmd_log_walk(struct rev_info *rev)return retval; } -static int git_log_config (const char *var,const char *value,void *cb) +static int git_log_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -608,7 +609,7 @@ static int git_log_config(const char *var, const char *value, void *cb)return 0 ; } -return git_diff_ui_config (var, value, cb); +return git_diff_ui_config (var, value,kvi, cb); }int cmd_whatchanged (int argc,const char **argv,const char *prefix)
@@ -974,7 +975,8 @@ static enum cover_from_description parse_cover_from_description(const char *arg)die (_ ("%s: invalid cover from description mode" ), arg); } -static int git_format_config (const char *var,const char *value,void *cb) +static int git_format_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"format.headers" )) {if (!value)
@@ -1103,7 +1105,7 @@ static int git_format_config(const char *var, const char *value, void *cb)if (!strcmp (var,"diff.noprefix" ))return 0 ; -return git_log_config (var, value, cb); +return git_log_config (var, value,kvi, cb); }static const char *output_directory =NULL ;
builtin/merge.c +4 -3
@@ -620,7 +620,8 @@ static void parse_branch_merge_options(char *bmo)free (argv); } -static int git_merge_config (const char *k,const char *v,void *cb) +static int git_merge_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {int status;const char *str;
@@ -665,10 +666,10 @@ static int git_merge_config(const char *k, const char *v, void *cb)return 0 ; } - status =fmt_merge_msg_config (k, v, cb); + status =fmt_merge_msg_config (k, v,kvi, cb);if (status)return status; -return git_diff_ui_config (k, v, cb); +return git_diff_ui_config (k, v,kvi, cb); } static int read_tree_trivial(struct object_id *common, struct object_id *head,
builtin/multi-pack-index.c +1 -0
@@ -82,6 +82,7 @@ static struct option *add_common_options(struct option *prev) }static int git_multi_pack_index_write_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var,"pack.writebitmaphashcache" )) {
builtin/pack-objects.c +3 -2
@@ -3134,7 +3134,8 @@ static void prepare_pack(int window, int depth)free (delta_list); } -static int git_pack_config (const char *k,const char *v,void *cb) +static int git_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"pack.window" )) { window =git_config_int (k, v);
@@ -3226,7 +3227,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) ex->uri =xstrdup (pack_end +1 );oidmap_put (&configured_exclusions, ex); } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }/* Counters for trace2 output when in --stdin-packs mode. */
builtin/patch-id.c +3 -2
@@ -196,7 +196,8 @@ struct patch_id_opts {int verbatim; }; -static int git_patch_id_config (const char *var,const char *value,void *cb) +static int git_patch_id_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct patch_id_opts *opts = cb;
@@ -209,7 +210,7 @@ static int git_patch_id_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_patch_id (int argc,const char **argv,const char *prefix)
builtin/pull.c +3 -2
@@ -359,7 +359,8 @@ static enum rebase_type config_get_rebase(int *rebase_unspecified)/** * Read config variables. */ -static int git_pull_config (const char *var,const char *value,void *cb) +static int git_pull_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"rebase.autostash" )) { config_autostash =git_config_bool (var, value);
@@ -372,7 +373,7 @@ static int git_pull_config(const char *var, const char *value, void *cb) check_trust_level =0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/**
builtin/push.c +3 -2
@@ -506,7 +506,8 @@ static void set_push_cert_flags(int *flags, int v) } -static int git_push_config (const char *k,const char *v,void *cb) +static int git_push_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {const char *slot_name;int *flags = cb;
@@ -573,7 +574,7 @@ static int git_push_config(const char *k, const char *v, void *cb)return 0 ; } -return git_default_config (k, v,NULL ); +return git_default_config (k, v,kvi,NULL ); }int cmd_push (int argc,const char **argv,const char *prefix)
builtin/read-tree.c +3 -2
@@ -100,12 +100,13 @@ static int debug_merge(const struct cache_entry * const *stages,return 0 ; } -static int git_read_tree_config (const char *var,const char *value,void *cb) +static int git_read_tree_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"submodule.recurse" ))return git_default_submodule_config (var, value, cb); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_read_tree (int argc,const char **argv,const char *cmd_prefix)
builtin/rebase.c +3 -2
@@ -791,7 +791,8 @@ static void parse_rebase_merges_value(struct rebase_options *options, const chardie (_ ("Unknown rebase-merges mode: %s" ), value); } -static int rebase_config (const char *var,const char *value,void *data) +static int rebase_config (const char *var,const char *value, +struct key_value_info *kvi,void *data) {struct rebase_options *opts = data;
@@ -850,7 +851,7 @@ static int rebase_config(const char *var, const char *value, void *data)return git_config_string (&opts->default_backend, var, value); } -return git_default_config (var, value, data); +return git_default_config (var, value,kvi, data); }static int checkout_up_to_date (struct rebase_options *options)
builtin/receive-pack.c +3 -2
@@ -135,7 +135,8 @@ static enum deny_action parse_deny_action(const char *var, const char *value)return DENY_IGNORE ; } -static int receive_pack_config (const char *var,const char *value,void *cb) +static int receive_pack_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {int status =parse_hide_refs_config (var, value,"receive" , &hidden_refs);
@@ -262,7 +263,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void show_ref (const char *path,const struct object_id *oid)
builtin/reflog.c +4 -3
@@ -108,7 +108,8 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)#define EXPIRE_TOTAL 01#define EXPIRE_UNREACH 02 -static int reflog_expire_config (const char *var,const char *value,void *cb) +static int reflog_expire_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *pattern, *key;size_t pattern_len;
@@ -117,7 +118,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)struct reflog_expire_cfg *ent;if (parse_config_key (var,"gc" , &pattern, &pattern_len, &key) <0 ) -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb);if (!strcmp (key,"reflogexpire" )) { slot =EXPIRE_TOTAL ;
@@ -128,7 +129,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)if (git_config_expiry_date (&expire, var, value))return -1 ; }else -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb);if (!pattern) {switch (slot) {
builtin/remote.c +4 -2
@@ -268,6 +268,7 @@ static const char *abbrev_ref(const char *name, const char *prefix)#define abbrev_branch (name) abbrev_ref((name), "refs/heads/")static int config_read_branches (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {const char *orig_key = key;
@@ -645,7 +646,7 @@ struct push_default_info };static int config_read_push_default (const char *key,const char *value, -void *cb) + struct key_value_info *kvi UNUSED, void *cb) {struct push_default_info * info = cb; if (strcmp(key, "remote.pushdefault") ||
@@ -1494,7 +1495,8 @@ static int prune(int argc, const char **argv, const char *prefix)return result; } -static int get_remote_default(const char *key, const char *value UNUSED, void *priv) +static int get_remote_default(const char *key, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *priv) {if (strcmp (key,"remotes.default" ) ==0 ) {int *found = priv;
builtin/repack.c +3 -2
@@ -58,7 +58,8 @@ struct pack_objects_args {int local; }; -static int repack_config (const char *var,const char *value,void *cb) +static int repack_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct pack_objects_args *cruft_po_args = cb;if (!strcmp (var,"repack.usedeltabaseoffset" )) {
@@ -90,7 +91,7 @@ static int repack_config(const char *var, const char *value, void *cb)return git_config_string (&cruft_po_args->depth, var, value);if (!strcmp (var,"repack.cruftthreads" ))return git_config_string (&cruft_po_args->threads, var, value); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
builtin/reset.c +3 -2
@@ -308,12 +308,13 @@ static int reset_refs(const char *rev, const struct object_id *oid)return update_ref_status; } -static int git_reset_config (const char *var,const char *value,void *cb) +static int git_reset_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"submodule.recurse" ))return git_default_submodule_config (var, value, cb); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_reset (int argc,const char **argv,const char *prefix)
builtin/send-pack.c +3 -2
@@ -131,7 +131,8 @@ static void print_helper_status(struct ref *ref)strbuf_release (&buf); } -static int send_pack_config (const char *k,const char *v,void *cb) +static int send_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"push.gpgsign" )) {const char *value;
@@ -151,7 +152,7 @@ static int send_pack_config(const char *k, const char *v, void *cb) } } } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }int cmd_send_pack (int argc,const char **argv,const char *prefix)
builtin/show-branch.c +3 -2
@@ -556,7 +556,8 @@ static void append_one_rev(const char *av)die ("bad sha1 reference %s" , av); } -static int git_show_branch_config (const char *var,const char *value,void *cb) +static int git_show_branch_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"showbranch.default" )) {if (!value)
@@ -579,7 +580,7 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int omit_in_dense (struct commit *commit,struct commit **rev,int n)
builtin/stash.c +3 -2
@@ -836,7 +836,8 @@ static int show_stat = 1;static int show_patch;static int show_include_untracked; -static int git_stash_config (const char *var,const char *value,void *cb) +static int git_stash_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"stash.showstat" )) { show_stat =git_config_bool (var, value);
@@ -850,7 +851,7 @@ static int git_stash_config(const char *var, const char *value, void *cb) show_include_untracked =git_config_bool (var, value);return 0 ; } -return git_diff_basic_config (var, value, cb); +return git_diff_basic_config (var, value,kvi, cb); }static void diff_include_untracked (const struct stash_info *info,struct diff_options *diff_opt)
builtin/submodule--helper.c +1 -0
@@ -2187,6 +2187,7 @@ static int update_clone_task_finished(int result, }static int git_update_clone_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *cb) {int *max_jobs = cb;
builtin/tag.c +3 -2
@@ -183,7 +183,8 @@ static const char tag_template_nocleanup[] ="Lines starting with '%c' will be kept; you may remove them" " yourself if you want to.\n"); -static int git_tag_config (const char *var,const char *value,void *cb) +static int git_tag_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"tag.gpgsign" )) { config_sign_tag =git_config_bool (var, value);
@@ -208,7 +209,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void write_tag_body (int fd,const struct object_id *oid)
builtin/var.c +3 -2
@@ -69,13 +69,14 @@ static const struct git_var *get_git_var(const char *var)return NULL ; } -static int show_config (const char *var,const char *value,void *cb) +static int show_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (value)printf ("%s=%s\n" , var, value);else printf ("%s\n" , var); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } int cmd_var(int argc, const char **argv, const char *prefix UNUSED)
builtin/worktree.c +3 -2
@@ -103,14 +103,15 @@ static int verbose;static int guess_remote;static timestamp_t expire; -static int git_worktree_config (const char *var,const char *value,void *cb) +static int git_worktree_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"worktree.guessremote" )) { guess_remote =git_config_bool (var, value);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int delete_git_dir (const char *id)
bundle-uri.c +6 -2
@@ -223,7 +223,9 @@ static int bundle_list_update(const char *key, const char *value,return 0 ; } -static int config_to_bundle_list (const char *key,const char *value,void *data) +static int config_to_bundle_list (const char *key,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct bundle_list *list = data;return bundle_list_update (key, value, list);
@@ -871,7 +873,9 @@ cached:return advertise_bundle_uri; } -static int config_to_packet_line (const char *key,const char *value,void *data) +static int config_to_packet_line (const char *key,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct packet_reader *writer = data;
config.c +18 -10
@@ -156,7 +156,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, +struct key_value_info *kvi,void *data);#define MAX_INCLUDE_DEPTH 10 static const char include_depth_advice[] = N_(
@@ -336,7 +337,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, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *remote_urls = data;const char *remote_name;
@@ -364,6 +366,7 @@ static void populate_remote_urls(struct config_include_data *inc) } static int forbid_remote_url(const char *var, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *data UNUSED) {const char *remote_name;
@@ -429,7 +432,8 @@ static int include_condition_is_true(struct key_value_info *kvi,static int kvi_fn (config_fn_t fn,const char *key,const char *value,struct key_value_info *kvi,void *data); -static int git_config_include (const char *var,const char *value,void *data) +static int git_config_include (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct config_include_data *inc = data;struct key_value_info *kvi = inc->config_reader->config_kvi;
@@ -1541,7 +1545,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, +struct key_value_info *kvi,void *cb) {/* This needs a better name */ if (!strcmp (var,"core.filemode" )) {
@@ -1826,7 +1831,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,kvi, cb); }static int git_default_sparse_config (const char *var,const char *value)
@@ -1928,15 +1933,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, +struct key_value_info *kvi,void *cb) {if (starts_with (var,"core." )) -return git_default_core_config (var, value, cb); +return git_default_core_config (var, value,kvi, 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,kvi, cb);if (starts_with (var,"i18n." ))return git_default_i18n_config (var, value);
@@ -2455,7 +2461,8 @@ 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, + struct key_value_info *kvi UNUSED, void *cb) {struct configset_add_data *data = cb;configset_add_value (data->config_reader, data->config_set, key, value);
@@ -3063,7 +3070,8 @@ static int store_aux_event(enum config_event_t type, size_t begin, size_t end,return 0 ; } -static int store_aux (const char *key,const char *value,void *cb) +static int store_aux (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct config_store_data *store = cb;
config.h +2 -1
@@ -146,7 +146,8 @@ struct key_value_info {*/ typedef int (*config_fn_t )(const char *,const char *,struct key_value_info *,void *); -int git_default_config (const char *,const char *,void *); +int git_default_config (const char *,const char *,struct key_value_info *, +void *);/** * Read a specific file in git-config format.
connect.c +2 -2
@@ -962,7 +962,7 @@ static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)static char *git_proxy_command;static int git_proxy_command_options (const char *var,const char *value, -void *cb) +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"core.gitproxy" )) {const char *for_pos;
@@ -1008,7 +1008,7 @@ static int git_proxy_command_options(const char *var, const char *value,return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int git_use_proxy (const char *host)
convert.c +3 -1
@@ -1011,7 +1011,9 @@ static int apply_filter(const char *path, const char *src, size_t len,return 0 ; } -static int read_convert_config(const char *var, const char *value, void *cb UNUSED) +static int read_convert_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, + void *cb UNUSED) {const char *key, *name;size_t namelen;
credential.c +1 -0
@@ -46,6 +46,7 @@ static int credential_from_potentially_partial_url(struct credential *c, const char *url);static int credential_config_callback (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *data) {struct credential *c = data;
delta-islands.c +2 -1
@@ -341,7 +341,8 @@ static void free_remote_islands(kh_str_t *remote_islands)kh_destroy_str (remote_islands); } -static int island_config_callback (const char *k,const char *v,void *cb) +static int island_config_callback (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {struct island_load_data *ild = cb;
diff.c +6 -4
@@ -350,7 +350,8 @@ static unsigned parse_color_moved_ws(const char *arg)return ret; } -int git_diff_ui_config (const char *var,const char *value,void *cb) +int git_diff_ui_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"diff.color" ) || !strcmp (var,"color.diff" )) { diff_use_color_default =git_config_colorbool (var, value);
@@ -433,10 +434,11 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_diff_basic_config (var, value, cb); +return git_diff_basic_config (var, value,kvi, cb); } -int git_diff_basic_config (const char *var,const char *value,void *cb) +int git_diff_basic_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *name;
@@ -488,7 +490,7 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)if (git_diff_heuristic_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static char *quote_two (const char *one,const char *two)
diff.h +4 -2
@@ -532,10 +532,12 @@ void free_diffstat_info(struct diffstat_t *diffstat);int parse_long_opt (const char *opt,const char **argv,const char **optarg); -int git_diff_basic_config (const char *var,const char *value,void *cb); +int git_diff_basic_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);int git_diff_heuristic_config (const char *var,const char *value,void *cb);void init_diff_ui_defaults (void ); -int git_diff_ui_config (const char *var,const char *value,void *cb); +int git_diff_ui_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);void repo_diff_setup (struct repository *,struct diff_options *);struct option *add_diff_options (const struct option *,struct diff_options *);int diff_opt_parse (struct diff_options *,const char **,int ,const char *);
fetch-pack.c +3 -2
@@ -1858,7 +1858,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,return ref; } -static int fetch_pack_config_cb (const char *var,const char *value,void *cb) +static int fetch_pack_config_cb (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (strcmp (var,"fetch.fsck.skiplist" ) ==0 ) {const char *path;
@@ -1880,7 +1881,7 @@ static int fetch_pack_config_cb(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void fetch_pack_config (void )
fmt-merge-msg.c +3 -2
@@ -19,7 +19,8 @@ static int use_branch_desc;static int suppress_dest_pattern_seen;static struct string_list suppress_dest_patterns =STRING_LIST_INIT_DUP ; -int fmt_merge_msg_config (const char *key,const char *value,void *cb) +int fmt_merge_msg_config (const char *key,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (key,"merge.log" ) || !strcmp (key,"merge.summary" )) {int is_bool;
@@ -39,7 +40,7 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)string_list_append (&suppress_dest_patterns, value); suppress_dest_pattern_seen =1 ; }else { -return git_default_config (key, value, cb); +return git_default_config (key, value,kvi, cb); }return 0 ; }
fmt-merge-msg.h +2 -1
@@ -13,7 +13,8 @@ struct fmt_merge_msg_opts { };extern int merge_log_config; -int fmt_merge_msg_config (const char *key,const char *value,void *cb); +int fmt_merge_msg_config (const char *key,const char *value, +struct key_value_info *kvi,void *cb);int fmt_merge_msg (struct strbuf *in,struct strbuf *out,struct fmt_merge_msg_opts *);
fsck.c +5 -3
@@ -1162,7 +1162,8 @@ struct fsck_gitmodules_data {int ret; }; -static int fsck_gitmodules_fn (const char *var,const char *value,void *vdata) +static int fsck_gitmodules_fn (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *vdata) {struct fsck_gitmodules_data *data = vdata;const char *subsection, *key;
@@ -1373,7 +1374,8 @@ int fsck_finish(struct fsck_options *options)return ret; } -int git_fsck_config (const char *var,const char *value,void *cb) +int git_fsck_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct fsck_options *options = cb;if (strcmp (var,"fsck.skiplist" ) ==0 ) {
@@ -1394,7 +1396,7 @@ int git_fsck_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
fsck.h +2 -1
@@ -237,6 +237,7 @@ const char *fsck_describe_object(struct fsck_options *options,* git_config() callback for use by fsck-y tools that want to support * fsck.<msg> fsck.skipList etc. */ -int git_fsck_config (const char *var,const char *value,void *cb); +int git_fsck_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);#endif
gpg-interface.c +4 -2
@@ -12,7 +12,8 @@#include "alias.h" #include "wrapper.h" -static int git_gpg_config (const char *,const char *,void *); +static int git_gpg_config (const char *,const char *,struct key_value_info *, +void *);static void gpg_interface_lazy_init (void ) {
@@ -718,7 +719,8 @@ void set_signing_key(const char *key) configured_signing_key =xstrdup (key); } -static int git_gpg_config(const char *var, const char *value, void *cb UNUSED) +static int git_gpg_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct gpg_format *fmt =NULL ;char *fmtname =NULL ;
grep.c +2 -1
@@ -54,7 +54,8 @@ define_list_config_array_extra(color_grep_slots, {"match"});* Read the configuration file once and store it in * the grep_defaults template. */ -int grep_config (const char *var,const char *value,void *cb) +int grep_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct grep_opt *opt = cb;const char *slot;
help.c +5 -2
@@ -309,7 +309,8 @@ void load_command_list(const char *prefix,exclude_cmds (other_cmds, main_cmds); } -static int get_colopts (const char *var,const char *value,void *data) +static int get_colopts (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {unsigned int *colopts = data;
@@ -459,7 +460,8 @@ void list_developer_interfaces_help(void)putchar ('\n' ); } -static int get_alias (const char *var,const char *value,void *data) +static int get_alias (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *list = data;
@@ -543,6 +545,7 @@ static struct cmdnames aliases;#define AUTOCORRECT_IMMEDIATELY (-1)static int git_unknown_cmd_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *p;
ident.c +2 -1
@@ -671,7 +671,8 @@ static int set_ident(const char *var, const char *value)return 0 ; } -int git_ident_config(const char *var, const char *value, void *data UNUSED) +int git_ident_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var,"user.useconfigonly" )) { ident_use_config_only =git_config_bool (var, value);
ident.h +2 -1
@@ -62,6 +62,7 @@ const char *fmt_name(enum want_ident);int committer_ident_sufficiently_given (void );int author_ident_sufficiently_given (void ); -int git_ident_config (const char *,const char *,void *); +int git_ident_config (const char *,const char *, +struct key_value_info *UNUSED ,void *);#endif
imap-send.c +3 -2
@@ -1322,7 +1322,8 @@ static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)return 1 ; } -static int git_imap_config (const char *var,const char *val,void *cb) +static int git_imap_config (const char *var,const char *val, +struct key_value_info *kvi,void *cb) {if (!strcmp ("imap.sslverify" , var))
@@ -1356,7 +1357,7 @@ static int git_imap_config(const char *var, const char *val, void *cb) server.host =xstrdup (val); } }else -return git_default_config (var, val, cb); +return git_default_config (var, val,kvi, cb);return 0 ; }
ll-merge.c +1 -0
@@ -252,6 +252,7 @@ static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;static const char *default_ll_merge;static int read_merge_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct ll_merge_driver *fn;
ls-refs.c +1 -1
@@ -136,7 +136,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data) }static int ls_refs_config (const char *var,const char *value, -void *cb_data) + struct key_value_info *kvi UNUSED, void *cb_data) {struct ls_refs_data *data = cb_data;/*
mailinfo.c +3 -2
@@ -1241,12 +1241,13 @@ int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action)return 0 ; } -static int git_mailinfo_config (const char *var,const char *value,void *mi_) +static int git_mailinfo_config (const char *var,const char *value, +struct key_value_info *kvi,void *mi_) {struct mailinfo *mi = mi_;if (!starts_with (var,"mailinfo." )) -return git_default_config (var, value,NULL ); +return git_default_config (var, value,kvi,NULL );if (!strcmp (var,"mailinfo.scissors" )) { mi->use_scissors =git_config_bool (var, value);return 0 ;
notes-utils.c +2 -1
@@ -93,7 +93,8 @@ static combine_notes_fn parse_combine_notes_fn(const char *v)return NULL ; } -static int notes_rewrite_config (const char *k,const char *v,void *cb) +static int notes_rewrite_config (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {struct notes_rewrite_cfg *c = cb;if (starts_with (k,"notes.rewrite." ) && !strcmp (k+14 , c->cmd)) {
notes.c +2 -1
@@ -973,7 +973,8 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,free (globs_copy); } -static int notes_display_config (const char *k,const char *v,void *cb) +static int notes_display_config (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {int *load_refs = cb;
pager.c +4 -1
@@ -39,6 +39,7 @@ static void wait_for_pager_signal(int signo) }static int core_pager_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var,"core.pager" ))
@@ -224,7 +225,9 @@ struct pager_command_config_data {char *value; }; -static int pager_command_config (const char *var,const char *value,void *vdata) +static int pager_command_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *vdata) {struct pager_command_config_data *data = vdata;const char *cmd;
pretty.c +1 -0
@@ -55,6 +55,7 @@ static void save_user_format(struct rev_info *rev, const char *cp, int is_tforma }static int git_pretty_formats_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct cmt_fmt_map *commit_format =NULL ;
promisor-remote.c +3 -1
@@ -99,7 +99,9 @@ static void promisor_remote_move_to_tail(struct promisor_remote_config *config, config->promisors_tail = &r->next; } -static int promisor_remote_config (const char *var,const char *value,void *data) +static int promisor_remote_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct promisor_remote_config *config = data;const char *name;
remote.c +2 -1
@@ -348,7 +348,8 @@ static void read_branches_file(struct remote_state *remote_state, remote->fetch_tags =1 ;/* always auto-follow */ } -static int handle_config (const char *key,const char *value,void *cb) +static int handle_config (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {const char *name;size_t namelen;
revision.c +2 -1
@@ -1569,7 +1569,8 @@ struct exclude_hidden_refs_cb {const char *section; }; -static int hide_refs_config (const char *var,const char *value,void *cb_data) +static int hide_refs_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb_data) {struct exclude_hidden_refs_cb *cb = cb_data; cb->exclusions->hidden_refs_configured =1 ;
scalar.c +2 -1
@@ -593,7 +593,8 @@ static int cmd_register(int argc, const char **argv)return register_dir (); } -static int get_scalar_repos (const char *key,const char *value,void *data) +static int get_scalar_repos (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *list = data;
sequencer.c +5 -3
@@ -214,7 +214,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)return rec; } -static int git_sequencer_config (const char *k,const char *v,void *cb) +static int git_sequencer_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct replay_opts *opts = cb;int status;
@@ -269,7 +270,7 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)if (opts->action ==REPLAY_REVERT && !strcmp (k,"revert.reference" )) opts->commit_use_reference =git_config_bool (k, v); -return git_diff_basic_config (k, v,NULL ); +return git_diff_basic_config (k, v,kvi,NULL ); }void sequencer_init_config (struct replay_opts *opts)
@@ -2876,7 +2877,8 @@ static int git_config_string_dup(char **dest,return 0 ; } -static int populate_opts_cb (const char *key,const char *value,void *data) +static int populate_opts_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct replay_opts *opts = data;int error_flag =1 ;
setup.c +10 -5
@@ -514,7 +514,9 @@ no_prevention_needed: startup_info->original_cwd =NULL ; } -static int read_worktree_config (const char *var,const char *value,void *vdata) +static int read_worktree_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *vdata) {struct repository_format *data = vdata;
@@ -585,7 +587,8 @@ static enum extension_result handle_extension(const char *var,return EXTENSION_UNKNOWN ; } -static int check_repo_format (const char *var,const char *value,void *vdata) +static int check_repo_format (const char *var,const char *value, +struct key_value_info *kvi,void *vdata) {struct repository_format *data = vdata;const char *ext;
@@ -614,7 +617,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata) } } -return read_worktree_config (var, value, vdata); +return read_worktree_config (var, value,kvi, vdata); }static int check_repository_format_gently (const char *gitdir,struct repository_format *candidate,int *nongit_ok)
@@ -1113,7 +1116,8 @@ struct safe_directory_data {int is_safe; }; -static int safe_directory_cb (const char *key,const char *value,void *d) +static int safe_directory_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct safe_directory_data *data = d;
@@ -1169,7 +1173,8 @@ static int ensure_valid_ownership(const char *gitfile,return data.is_safe; } -static int allowed_bare_repo_cb (const char *key,const char *value,void *d) +static int allowed_bare_repo_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {enum allowed_bare_repo *allowed_bare_repo = d;
submodule-config.c +11 -4
@@ -424,7 +424,8 @@ struct parse_config_parameter {* config store (.git/config, etc). Callers are responsible for * checking for overrides in the main config store when appropriate. */ -static int parse_config (const char *var,const char *value,void *data) +static int parse_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct parse_config_parameter *me = data;struct submodule *submodule;
@@ -673,7 +674,8 @@ out: } } -static int gitmodules_cb (const char *var,const char *value,void *data) +static int gitmodules_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct repository *repo = data;struct parse_config_parameter parameter;
@@ -801,7 +803,9 @@ void submodule_free(struct repository *r)submodule_cache_clear (r->submodule_cache); } -static int config_print_callback (const char *var,const char *value,void *cb_data) +static int config_print_callback (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {char *wanted_key = cb_data;
@@ -843,7 +847,9 @@ struct fetch_config {int *recurse_submodules; }; -static int gitmodules_fetch_config (const char *var,const char *value,void *cb) +static int gitmodules_fetch_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb) {struct fetch_config *config = cb;if (!strcmp (var,"submodule.fetchjobs" )) {
@@ -871,6 +877,7 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules) }static int gitmodules_update_clone_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *cb) {int *max_jobs = cb;
t/helper/test-config.c +6 -3
@@ -42,7 +42,8 @@* */ -static int iterate_cb(const char *var, const char *value, void *data UNUSED) +static int iterate_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {static int nr;
@@ -59,7 +60,8 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)return 0 ; } -static int parse_int_cb (const char *var,const char *value,void *data) +static int parse_int_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {const char *key_to_match = data;
@@ -70,7 +72,8 @@ static int parse_int_cb(const char *var, const char *value, void *data)return 0 ; } -static int early_config_cb (const char *var,const char *value,void *vdata) +static int early_config_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *vdata) {const char *key = vdata;
t/helper/test-userdiff.c +3 -1
@@ -12,7 +12,9 @@ static int driver_cb(struct userdiff_driver *driver,return 0 ; } -static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED) +static int cmd__userdiff_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, + void *cb UNUSED) {if (userdiff_config (var, value) <0 )return -1 ;
trace2/tr2_cfg.c +2 -1
@@ -99,7 +99,8 @@ 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,void *d) +static int tr2_cfg_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct strbuf **s;struct tr2_cfg_data *data = (struct tr2_cfg_data *)d;
trace2/tr2_sysenv.c +2 -1
@@ -57,7 +57,8 @@ static struct tr2_sysenv_entry tr2_sysenv_settings[] = { };/* clang-format on */ -static int tr2_sysenv_cb (const char *key,const char *value,void *d) +static int tr2_sysenv_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {int k;
trailer.c +2 -0
@@ -482,6 +482,7 @@ static struct { };static int git_trailer_default_config (const char *conf_key,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *trailer_item, *variable_name;
@@ -514,6 +515,7 @@ static int git_trailer_default_config(const char *conf_key, const char *value, }static int git_trailer_config (const char *conf_key,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *trailer_item, *variable_name;
upload-pack.c +6 -2
@@ -1298,7 +1298,9 @@ static int parse_object_filter_config(const char *var, const char *value,return 0 ; } -static int upload_pack_config (const char *var,const char *value,void *cb_data) +static int upload_pack_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {struct upload_pack_data *data = cb_data;
@@ -1339,7 +1341,9 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)return parse_hide_refs_config (var, value,"uploadpack" , &data->hidden_refs); } -static int upload_pack_protected_config (const char *var,const char *value,void *cb_data) +static int upload_pack_protected_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {struct upload_pack_data *data = cb_data;
urlmatch.c +2 -1
@@ -551,7 +551,8 @@ static int cmp_matches(const struct urlmatch_item *a,return 0 ; } -int urlmatch_config_entry (const char *var,const char *value,void *cb) +int urlmatch_config_entry (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct string_list_item *item;struct urlmatch_config *collect = cb;
urlmatch.h +2 -1
@@ -71,7 +71,8 @@ struct urlmatch_config { .vars = STRING_LIST_INIT_DUP, \ } -int urlmatch_config_entry (const char *var,const char *value,void *cb); +int urlmatch_config_entry (const char *var,const char *value, +struct key_value_info *kvi,void *cb);void urlmatch_config_release (struct urlmatch_config *config);#endif /* URL_MATCH_H */
xdiff-interface.c +3 -2
@@ -307,7 +307,8 @@ int xdiff_compare_lines(const char *l1, long s1,int git_xmerge_style =-1 ; -int git_xmerge_config (const char *var,const char *value,void *cb) +int git_xmerge_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"merge.conflictstyle" )) {if (!value)
@@ -327,5 +328,5 @@ int git_xmerge_config(const char *var, const char *value, void *cb) value, var);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }
xdiff-interface.h +2 -1
@@ -50,7 +50,8 @@ int buffer_is_binary(const char *ptr, unsigned long size);void xdiff_set_find_func (xdemitconf_t *xecfg,const char *line,int cflags);void xdiff_clear_find_func (xdemitconf_t *xecfg); -int git_xmerge_config (const char *var,const char *value,void *cb); +int git_xmerge_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);extern int git_xmerge_style;/*
Signature · 1 line
gitgitgadget
PATCH 13/14 config: pass kvi to die_bad_number()
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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".
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_<type>() can pass it to git_config_<type>().
Outside of config.c, config callbacks now need to pass "kvi" to any of the git_config_<type>() functions that parse a config string into a number type. Included is a .cocci patch to make that refactor. In cases where "kvi" would never be used, pass NULL, e.g.:
- In config.c, when we are parsing a boolean instead of a number
- In builtin/config.c, when calling normalize_value() before setting config to something the user gave us.
--- archive-tar.c | 4 +- builtin/commit-graph.c | 4 +- builtin/commit.c | 10 +- builtin/config.c | 20 ++-- 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 | 128 +++++++++------------ config.h | 14 ++- contrib/coccinelle/git_config_number.cocci | 27 +++++ diff.c | 9 +- fmt-merge-msg.c | 2 +- help.c | 5 +- http.c | 10 +- imap-send.c | 2 +- sequencer.c | 22 ++-- setup.c | 2 +- submodule-config.c | 15 ++- submodule-config.h | 3 +- t/helper/test-config.c | 6 +- upload-pack.c | 12 +- worktree.c | 2 +- 27 files changed, 182 insertions(+), 161 deletions(-) create mode 100644 contrib/coccinelle/git_config_number.cocci
archive-tar.c +2 -2
@@ -411,14 +411,14 @@ static int tar_filter_config(const char *var, const char *value, }static int git_tar_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,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, kvi); }return 0 ; }
builtin/commit-graph.c +2 -2
@@ -185,11 +185,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, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi, 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, kvi);/* * No need to fall-back to 'git_default_config', since this was already * called in 'cmd_commit_graph()'.
builtin/commit.c +6 -4
@@ -1412,7 +1412,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, kvi, + &is_bool);if (is_bool && s->submodule_summary) s->submodule_summary =-1 ;return 0 ;
@@ -1472,11 +1473,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, kvi);return 0 ; }if (!strcmp (k,"status.renamelimit" )) { - s->rename_limit =git_config_int (k, v); + s->rename_limit =git_config_int (k, v, kvi);return 0 ; }if (!strcmp (k,"diff.renames" )) {
@@ -1622,7 +1623,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, kvi, + &is_bool);return 0 ; }
builtin/config.c +11 -9
@@ -254,13 +254,14 @@ static int format_config(struct strbuf *buf, const char *key_, const char *valueif (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
@@ -411,7 +412,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 ;
@@ -426,12 +428,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
@@ -870,7 +872,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 ],NULL ); 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"
@@ -879,7 +881,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 ],NULL ); ret =git_config_set_multivar_in_file_gently (given_config_source.file, argv[0 ], value, argv[2 ], flags);
@@ -887,7 +889,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 ],NULL ); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, CONFIG_REGEX_NONE,
@@ -896,7 +898,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 ],NULL ); ret =git_config_set_multivar_in_file_gently (given_config_source.file, argv[0 ], value, argv[2 ], flags |CONFIG_FLAGS_MULTI_REPLACE );
builtin/fetch.c +2 -2
@@ -125,7 +125,7 @@ static int git_fetch_config(const char *k, const char *v, }if (!strcmp (k,"submodule.fetchjobs" )) { - submodule_fetch_jobs_config =parse_submodule_fetchjobs (k, v); + submodule_fetch_jobs_config =parse_submodule_fetchjobs (k, v, kvi);return 0 ; }else if (!strcmp (k,"fetch.recursesubmodules" )) { recurse_submodules =parse_fetch_recurse_submodules_arg (k, v);
@@ -133,7 +133,7 @@ static int git_fetch_config(const char *k, const char *v, }if (!strcmp (k,"fetch.parallel" )) { - fetch_parallel_config =git_config_int (k, v); + fetch_parallel_config =git_config_int (k, v, kvi);if (fetch_parallel_config <0 )die (_ ("fetch.parallel cannot be negative" ));if (!fetch_parallel_config)
builtin/fsmonitor--daemon.c +3 -3
@@ -40,7 +40,7 @@ static int fsmonitor_config(const char *var, const char *value, struct key_value_info *kvi, void *cb) {if (!strcmp (var,FSMONITOR__IPC_THREADS )) { -int i =git_config_int (var, value); +int i =git_config_int (var, value, kvi);if (i <1 )return error (_ ("value of '%s' out of range: %d" ),FSMONITOR__IPC_THREADS , i);
@@ -49,7 +49,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, kvi);if (i <0 )return error (_ ("value of '%s' out of range: %d" ),FSMONITOR__START_TIMEOUT , i);
@@ -59,7 +59,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, kvi, &is_bool);if (i <0 )return error (_ ("value of '%s' not bool or int: %d" ), var, i);
builtin/grep.c +1 -1
@@ -298,7 +298,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, kvi);if (num_threads <0 )die (_ ("invalid number of threads specified (%d) for %s" ), num_threads, var);
builtin/index-pack.c +2 -2
@@ -1584,13 +1584,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, 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, kvi);if (nr_threads <0 )die (_ ("invalid number of threads specified (%d)" ), nr_threads);
builtin/log.c +1 -1
@@ -569,7 +569,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, kvi);return 0 ; }if (!strcmp (var,"format.encodeemailheaders" )) {
builtin/pack-objects.c +7 -7
@@ -3138,23 +3138,23 @@ static int git_pack_config(const char *k, const char *v, struct key_value_info *kvi, void *cb) {if (!strcmp (k,"pack.window" )) { - window =git_config_int (k, v); + window =git_config_int (k, v, kvi);return 0 ; }if (!strcmp (k,"pack.windowmemory" )) { - window_memory_limit =git_config_ulong (k, v); + window_memory_limit =git_config_ulong (k, v, kvi);return 0 ; }if (!strcmp (k,"pack.depth" )) { - depth =git_config_int (k, v); + depth =git_config_int (k, v, 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, 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, kvi);return 0 ; }if (!strcmp (k,"pack.writebitmaphashcache" )) {
@@ -3180,7 +3180,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, kvi);if (delta_search_threads <0 )die (_ ("invalid number of threads specified (%d)" ), delta_search_threads);
@@ -3191,7 +3191,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, kvi);if (pack_idx_opts.version >2 )die (_ ("bad pack.indexVersion=%" PRIu32), pack_idx_opts.version);
builtin/receive-pack.c +5 -5
@@ -154,12 +154,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, 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, kvi);return 0 ; }
@@ -227,7 +227,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, kvi);return 0 ; }
@@ -242,12 +242,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, 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, kvi);return 0 ; }
builtin/submodule--helper.c +2 -2
@@ -2187,13 +2187,13 @@ static int update_clone_task_finished(int result, }static int git_update_clone_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi,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, kvi);return 0 ; }
config.c +57 -71
323 lines not on this page · raw message
config.h +8 -6
@@ -237,22 +237,23 @@ 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 *,struct key_value_info *); -int64_t git_config_int64 (const char *,const char *); +int64_t git_config_int64 (const char *,const char *,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 *,struct key_value_info *); -ssize_t git_config_ssize_t (const char *,const char *); +ssize_t git_config_ssize_t (const char *,const char *,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 *,struct key_value_info *, +int *);/** * Parse a string into a boolean value, respecting keywords like "true" and
@@ -516,7 +517,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);
contrib/coccinelle/git_config_number.cocci new file +27 -0
@@ -0,0 +1,27 @@ +@@ +identifier C1, C2, C3; +@@ +( +( +git_config_int +| +git_config_int64 +| +git_config_ulong +| +git_config_ssize_t +) + (C1, C2 ++ , kvi + ) +| +( +git_configset_get_value +| +git_config_bool_or_int +) + (C1, C2, ++ kvi, + C3 + ) +)
diff.c +5 -4
@@ -372,13 +372,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, 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, + kvi);if (diff_interhunk_context_default <0 )return -1 ;return 0 ;
@@ -404,7 +405,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, kvi);return 0 ; }if (!strcmp (var,"diff.external" ))
@@ -443,7 +444,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, kvi);return 0 ; }
fmt-merge-msg.c +1 -1
@@ -24,7 +24,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, kvi, &is_bool);if (!is_bool && merge_log_config <0 )return error ("%s: negative length %s" , key, value);if (is_bool && merge_log_config)
help.c +2 -3
@@ -545,8 +545,7 @@ static struct cmdnames aliases;#define AUTOCORRECT_IMMEDIATELY (-1)static int git_unknown_cmd_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, - void *cb UNUSED) + struct key_value_info *kvi, void *cb UNUSED) {const char *p;
@@ -560,7 +559,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, kvi); autocorrect = (v <0 ) ?AUTOCORRECT_IMMEDIATELY : v; }
http.c +5 -5
@@ -412,21 +412,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, 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, 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, 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, kvi);return 0 ; }
@@ -462,7 +462,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, 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 )
imap-send.c +1 -1
@@ -1341,7 +1341,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, kvi);else if (!strcmp ("imap.host" , var)) {if (!val) {git_die_config ("imap.host" ,"Missing value for 'imap.host'" );
sequencer.c +11 -11
@@ -2878,7 +2878,7 @@ static int git_config_string_dup(char **dest, }static int populate_opts_cb (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {struct replay_opts *opts = data;int error_flag =1 ;
@@ -2886,26 +2886,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, 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, 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, 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, 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, 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, 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, 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, kvi, &error_flag);else if (!strcmp (key,"options.mainline" )) - opts->mainline =git_config_int (key, value); + opts->mainline =git_config_int (key, value, kvi);else if (!strcmp (key,"options.strategy" ))git_config_string_dup (&opts->strategy, key, value);else if (!strcmp (key,"options.gpg-sign" ))
@@ -2915,7 +2915,7 @@ static int populate_opts_cb(const char *key, const char *value, opts->xopts[opts->xopts_nr++] =xstrdup (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, kvi, &error_flag) ?RERERE_AUTOUPDATE :RERERE_NOAUTOUPDATE ;else if (!strcmp (key,"options.default-msg-cleanup" )) { opts->explicit_cleanup =1 ;
setup.c +1 -1
@@ -594,7 +594,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, kvi);else if (skip_prefix (var,"extensions." , &ext)) {switch (handle_extension_v0 (var, value, ext, data)) {case EXTENSION_ERROR :
submodule-config.c +7 -8
@@ -302,9 +302,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, +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)
@@ -848,14 +849,13 @@ struct fetch_config { };static int gitmodules_fetch_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, -void *cb) +struct key_value_info *kvi,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, kvi);return 0 ; }else if (!strcmp (var,"fetch.recursesubmodules" )) {if (config->recurse_submodules)
@@ -877,12 +877,11 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules) }static int gitmodules_update_clone_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, -void *cb) +struct key_value_info *kvi,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, kvi);return 0 ; }
submodule-config.h +2 -1
@@ -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, +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,
t/helper/test-config.c +3 -3
@@ -61,12 +61,12 @@ static int iterate_cb(const char *var, const char *value, }static int parse_int_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,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, kvi);printf ("%d\n" , parsed); }return 0 ;
@@ -179,7 +179,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
upload-pack.c +7 -5
@@ -1264,7 +1264,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) +struct key_value_info *kvi, +struct upload_pack_data *data) {struct strbuf buf =STRBUF_INIT ;const char *sub, *key;
@@ -1291,7 +1292,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);
@@ -1299,7 +1301,7 @@ static int parse_object_filter_config(const char *var, const char *value, }static int upload_pack_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi,void *cb_data) {struct upload_pack_data *data = cb_data;
@@ -1320,7 +1322,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, kvi);if (!data->keepalive) data->keepalive =-1 ; }else if (!strcmp ("uploadpack.allowfilter" , var)) {
@@ -1335,7 +1337,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, kvi, data) <0 )return -1 ;return parse_hide_refs_config (var, value,"uploadpack" , &data->hidden_refs);
worktree.c +1 -1
@@ -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)))
Signature · 1 line
gitgitgadget
Re: [PATCH 02/14] config.c: use kvi for CLI config
In reply to Glen Choo via GitGitGadgetconfig.c static int config_parse_pair(const char *key, const char *value, · line 683
Quoted 9 lines · Glen Choo via GitGitGadget
config.c +1
-1@@ -682,17 +677,30 @@ 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 = (kvi_fn (fn, canonical_name, value, kvi, data) <0 ) ?-1 :0 ;free (canonical_name);return ret; }
This is pre-existing, but I'd much prefer as we're doing more formalization of this interface if this were just:
ret = kvi_fn(...); ...; return ret;
I.e. a look at the current code shows us that the API users of git_config_parse_parameter() are already doing this coercion themselves, i.e. they only care about "ret < 0".
So let's just hand them the actual return value, rather than doing the needless coercion.
Quoted 11 lines
config.c +1
-3@@ -2423,19 +2429,13 @@ static int configset_add_value(struct config_reader *reader, 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) { +if (reader->source && reader->source->name) { kv_info->filename =strintern (reader->source->name); kv_info->linenr = reader->source->linenr; kv_info->origin_type = reader->source->origin_type;
config.c static int configset_add_value(struct config_reader *reader, · line 2438
Quoted 10 lines
config.c +3
-7- }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; + }else +kvi_from_param (kv_info);
Missing a {} here.
Re: [PATCH 10/14] (RFC-only) config: finish config_fn_t refactor
In reply to Glen Choo via GitGitGadgetQuoted 1 line · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
I like the general goal of this series, i.e. to get rid of the "reader" callback, and pass stuff more explicitly.
But as I pointed out in
https://lore.kernel.org/git/[email protected]/
I think this part (and the preceding two commits) are really taking is down the wrong path.
To demonstrate why, here's a patch-on-top of this topic as a whole where I renamed the "kvi" struct members. I've excluded config.c itself (as its internals aren't interesting for the purposes of this discussion):
diff --git a/builtin/config.c b/builtin/config.c
index c9e80a4b500..00cf8ffd791 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -198,8 +198,8 @@ static void show_config_origin(struct key_value_info *kvi, struct strbuf *buf)
- strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
+ strbuf_addstr(buf, config_origin_type_name(kvi->origin_type2));
strbuf_addch(buf, ':');
if (end_nul)
- strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
+ strbuf_addstr(buf, kvi->filename2 ? kvi->filename2 : "");
else
- quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
+ quote_c_style(kvi->filename2 ? kvi->filename2 : "", buf, NULL, 0);
strbuf_addch(buf, term);
@@ -210,3 +210,3 @@ static void show_config_scope(struct key_value_info *kvi, struct strbuf *buf)
const char term = end_nul ? '\0' : '\t';
- const char *scope = config_scope_name(kvi->scope);
+ const char *scope = config_scope_name(kvi->scope2);
diff --git a/builtin/remote.c b/builtin/remote.c
index 034998a1205..81922af3f58 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -655,6 +655,6 @@ static int config_read_push_default(const char *key, const char *value,
- info->scope = kvi->scope;
+ info->scope = kvi->scope2;
strbuf_reset(&info->origin);
- strbuf_addstr(&info->origin, kvi->filename);
- info->linenr = kvi->linenr;
+ strbuf_addstr(&info->origin, kvi->filename2);
+ info->linenr = kvi->linenr2;
diff --git a/config.h b/config.h
index ffb2d76823c..d9b0470e7b7 100644
--- a/config.h
+++ b/config.h
@@ -120,8 +120,8 @@ struct config_options {
struct key_value_info {
- const char *filename;
- int linenr;
- enum config_origin_type origin_type;
- enum config_scope scope;
- const char *path;
- struct key_value_info *prev;
+ const char *filename2;
+ int linenr2;
+ enum config_origin_type origin_type2;
+ enum config_scope scope2;
+ const char *path2;
+ struct key_value_info *prev2;
};
diff --git a/remote.c b/remote.c
index 5239dfeab55..1cb465c6c17 100644
--- a/remote.c
+++ b/remote.c
@@ -417,4 +417,4 @@ static int handle_config(const char *key, const char *value,
remote->origin = REMOTE_CONFIG;
- if (kvi->scope == CONFIG_SCOPE_LOCAL ||
- kvi->scope == CONFIG_SCOPE_WORKTREE)
+ if (kvi->scope2 == CONFIG_SCOPE_LOCAL ||
+ kvi->scope2 == CONFIG_SCOPE_WORKTREE)
remote->configured_in_repo = 1;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 737505583d4..fa89cdd084c 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -54,6 +54,6 @@ static int iterate_cb(const char *var, const char *value,
printf("value=%s\n", value ? value : "(null)");
- 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));
+ printf("origin=%s\n", config_origin_type_name(kvi->origin_type2));
+ printf("name=%s\n", kvi->filename2 ? kvi->filename2 : "");
+ printf("lno=%d\n", kvi->linenr2);
+ printf("scope=%s\n", config_scope_name(kvi->scope2));
diff --git a/trace2/tr2_tgt_event.c b/trace2/tr2_tgt_event.c
index 83db3c755bd..338c5a58bd9 100644
--- a/trace2/tr2_tgt_event.c
+++ b/trace2/tr2_tgt_event.c
@@ -482,3 +482,3 @@ static void fn_param_fl(const char *file, int line, const char *param,
struct json_writer jw = JSON_WRITER_INIT;
- enum config_scope scope = kvi->scope;
+ enum config_scope scope = kvi->scope2;
const char *scope_name = config_scope_name(scope);
diff --git a/trace2/tr2_tgt_normal.c b/trace2/tr2_tgt_normal.c
index 65e9be9c5a4..5a06042e7c3 100644
--- a/trace2/tr2_tgt_normal.c
+++ b/trace2/tr2_tgt_normal.c
@@ -301,3 +301,3 @@ static void fn_param_fl(const char *file, int line, const char *param,
struct strbuf buf_payload = STRBUF_INIT;
- enum config_scope scope = kvi->scope;
+ enum config_scope scope = kvi->scope2;
const char *scope_name = config_scope_name(scope);
diff --git a/trace2/tr2_tgt_perf.c b/trace2/tr2_tgt_perf.c
index f402f6e3813..96fa359183d 100644
--- a/trace2/tr2_tgt_perf.c
+++ b/trace2/tr2_tgt_perf.c
@@ -445,3 +445,3 @@ static void fn_param_fl(const char *file, int line, const char *param,
struct strbuf scope_payload = STRBUF_INIT;
- enum config_scope scope = kvi->scope;
+ enum config_scope scope = kvi->scope2;
const char *scope_name = config_scope_name(scope);So, as this shows us your 08/14 has gone through the effort of passing this "kvi" info to every single callback, but it's only this handful that actually needs this information.
So, even if we *can* get this to work I don't think it's worth it, especially as this would preclude giving these config callbacks some "lighter" API that doesn't take the trouble of recording and ferrying this information to them.
Of course *now* we need to always prepare this information anyway, as anyone could access it via a global, but as the work you've done here shows we're always doing that, but only need it for these few cases.
So I really think we could leave the vast majority of the current callbacks alone, and just supply a new "kvi" callback. My
https://lore.kernel.org/git/[email protected]/
showed one way forward with that.
I think this should also neatly answer some of your outstanding questions. Especially as the above shows that the only non-test caller that needs "linenr" is the builtin/config.c caller that my proposed RFC (linked above) tackled directly. Most of these callbacks just need the more basic "scope".
So, in particular:
Quoted 10 lines
Here's an exhaustive list of all of the changes:
* Cases that need a judgement call
- trace2/tr2_cfg.c:tr2_cfg_set_fl()
This function needs to account for
tr2_cfg_cb()now using "kvi". Since this is only called (indirectly) bygit_config_set(), config source information has never been available here, so just pass NULL. It will be tr2_cfg_cb()'s responsibility to not use "kvi".
Just adding a "CONFIG_SCOPE_IN_PROCESS", "CONFIG_SCOPE_SET" or whatever you'd want to call it seems to make much more sense here, no?
Quoted 6 lines
- builtin/checkout.c:checkout_main()
This calls
git_xmerge_config()as a shorthand for parsing a CLI arg. "kvi" doesn't apply, so just pass NULL. This might be worth refactoring away, sincegit_xmerge_config()can callgit_default_config().
Another example of a caller which never actually cares about this data, so if it doesn't need to have it passed to it, it doesn't need to fake it up either.
Quoted 4 lines
- config.c:git_config_include()
Replace the local "kvi" variable with the "kvi" parameter. This makes config_include_data.config_reader obsolete, so remove it.
No comment (internal to config.c, as noted above).
Quoted 11 lines
* Hard for cocci to catch
-
urlmatch.cManually refactor the custom config callbacks in "struct
urlmatch_config".-
diff.h,fsck.h,grep.h,ident.h,xdiff-interface.h"struct
key_value_info" hasn't been defined yet, so forward declare it. Alternatively, maybe these files should "#includeconfig.h".
All of these problems go away if you don't insist on changing every single caller, you'll just have a step where you remove the current global in favor of some "config callback with kvi" info, and "make" will spot those callers that aren't converted yet.
Those changes will be trivial enough (just the callers I noted above) to not require the tricky cocci patch in 08/14.
Quoted 23 lines
* Likely deficiencies in .cocci patch
- submodule-config.c:gitmodules_cb()
Manually refactor a
parse_config()call that gets missed because it uses a different "*data" arg.-
grep.h, variousManually refactor
grep_config()calls. Not sure why these don't get picked up.- config.c:git_config_include(), http.c:http_options()
Manually add "kvi" where it was missed. Not sure why they get missed.
- builtin/clone.c:write_one_config()
Manually refactor a
git_clone_config()call. Probably got missed because I didn't includegit_config_parse_parameter().-
ident.h
Quoted 8 lines
Remove the UNUSED attribute. Not sure why this is the only instance of this.
-
git-compat-util.h, compat/mingw.[h|c]Manually refactor
noop_core_config(),platform_core_config()andmingw_core_config(). I can probably add these as "manual fixups" in cocci.
ditto.
Re: [PATCH 10/14] (RFC-only) config: finish config_fn_t refactor
Quoted 8 lines · Ævar Arnfjörð Bjarmason
But as I pointed out in
https://lore.kernel.org/git/[email protected]/
I think this part (and the preceding two commits) are really taking is down the wrong path.To demonstrate why, here's a patch-on-top of this topic as a whole where I renamed the "kvi" struct members. I've excluded
config.citself (as its internals aren't interesting for the purposes of this discussion):
[snip patch showing where kvi is used]
Ah, thanks for this patch. One of my objections to your proposal in the aforementioned thread is that we would end up with a lot of callback- taking config functions that have 2 variants, one for the kvi callback and one for the non-kvi callback, but here your patch shows that it won't be the case.
Your approach does look like a reasonable one.
As for my own opinions, (before Ævar sent this email) I took a look at these patches myself and had some issues with at least the first 2: in patch 1, kvi_fn() replaces fn() for some but not all invocations of fn() (in patch 2, you can see one such invocation that was not changed), and I was having difficulty thinking of what kind of bugs I should watch out for since not all invocations were changed; and in patch 2, the safeguard of not setting kvi and source together was removed and likewise I was having difficulty thinking of what kind of bugs could occur from both being set at once inadvertently. I was going to suggest reordering the patches such that the large-scale refactoring (and any supporting patches like [PATCH 06/14] config: inline git_color_default_config) should occur first (or waiting for a reviewer who is convinced that patches 1 and 2 are OK, I guess), but having now seen that sidestepping a large part of this makes sense, sidestepping seems like a good idea to me.
Re: [PATCH 10/14] (RFC-only) config: finish config_fn_t refactor
In reply to Ævar Arnfjörð BjarmasonQuoted 16 lines · Ævar Arnfjörð Bjarmason
Quoted 1 line · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
I like the general goal of this series, i.e. to get rid of the "reader" callback, and pass stuff more explicitly.
But as I pointed out in
https://lore.kernel.org/git/[email protected]/
I think this part (and the preceding two commits) are really taking is down the wrong path.To demonstrate why, here's a patch-on-top of this topic as a whole where I renamed the "kvi" struct members. I've excluded
config.citself (as its internals aren't interesting for the purposes of this discussion):
Quoted 5 lines
[Patch showing used kvi members...]
So, as this shows us your 08/14 has gone through the effort of passing this "kvi" info to every single callback, but it's only this handful that actually needs this information.
The attached patch misses the majority of "kvi" users, which use it in die_bad_number(). This change happens in Patch 13/14, where the whole "kvi" is passed into config.c machinery. It's still a much smaller number of config callbacks than the ones changed in these few patches, but it's more than a handful, I'd think.
Quoted 4 lines
So, even if we *can* get this to work I don't think it's worth it, especially as this would preclude giving these config callbacks some "lighter" API that doesn't take the trouble of recording and ferrying this information to them.
I assume the "lighter API" refers to the current API?
If I'm reading this correctly, your concern isn't primarily about reducing churn, it's YAGNI - since most callers don't need this info, they should be able to reap the benefits of an API that doesn't provide that info. Thus, you're proposing to having both the current API and a new kvi-based one?
If so, I don't think that's a good route to take:
- Having both *_kvi() and "old" variants will add bloat to an already bloated config API. Even without further changes, we'd need to add *_kvi() to at least config_with_options() and repo_config(), as well as all of the functions that config_with_options() uses under the hood (some of which are public).
To some extent, this can be managed by shrinking the config API (e.g. like your suggestion to get rid of git_config_from_file() [1]), but IMO that needs more discussion.
- What benefit is the old API giving us vs the new one? It won't be any faster since the machinery will need to support the new API, and even if it were, the benefit would be tiny. In some cases it might be nice to use the config callback in a non-config setting, but this patch shows that those are rare and can be easily worked around.
- I strongly suspect that we'd already like "kvi" in more places, and if we made it readily available, we would add these additional callers. E.g. we already use it to give additional diagnostics when failing to parse a number, and there's no reason why we shouldn't do this when doing other kinds of parsing (e.g. date in git_config_expiry_date() or color in color_parse_mem()).
If your concern really is primarily about churn and we actually want to move everything to the new API eventually, wouldn't it be better to bite the bullet and take a one time, well-scoped churn cost instead of a longer migration?
[1] https://lore.kernel.org/git/[email protected]/
Quoted 5 lines
I think this should also neatly answer some of your outstanding questions. Especially as the above shows that the only non-test caller that needs "linenr" is the
builtin/config.ccaller that my proposed RFC (linked above) tackled directly. Most of these callbacks just need the more basic "scope".
I didn't see where builtin/config.c was handled in the above link. Perhaps you meant a different RFC,
https://github.com/avar/git/commit/0233297a359bbda43a902dd0213aacdca82faa34?
Quoted 8 lines
So, in particular:
Quoted 6 lines
Here's an exhaustive list of all of the changes:
* Cases that need a judgement call
- trace2/tr2_cfg.c:tr2_cfg_set_fl()
Quoted 7 lines
Quoted 4 lines
This function needs to account for
tr2_cfg_cb()now using "kvi". Since this is only called (indirectly) bygit_config_set(), config source information has never been available here, so just pass NULL. It will be tr2_cfg_cb()'s responsibility to not use "kvi".Just adding a "
CONFIG_SCOPE_IN_PROCESS", "CONFIG_SCOPE_SET" or whatever you'd want to call it seems to make much more sense here, no?
CONFIG_SCOPE_SET makes sense.
Quoted 10 lines
Quoted 6 lines
- builtin/checkout.c:checkout_main()
This calls
git_xmerge_config()as a shorthand for parsing a CLI arg. "kvi" doesn't apply, so just pass NULL. This might be worth refactoring away, sincegit_xmerge_config()can callgit_default_config().Another example of a caller which never actually cares about this data, so if it doesn't need to have it passed to it, it doesn't need to fake it up either.
Here's a case of YAGNI I mentioned above and I agree it would be nice to not have to fake a "kvi". However, git_xmerge_config() can call git_defualt_config() so this seems more like it's abusing the config callback to parse a CLI arg. A better resolution would be to have a function dedicated to parsing "merge.conflictstyle".
Quoted 46 lines
Quoted 11 lines
* Hard for cocci to catch
-
urlmatch.cManually refactor the custom config callbacks in "struct
urlmatch_config".-
diff.h,fsck.h,grep.h,ident.h,xdiff-interface.h"struct
key_value_info" hasn't been defined yet, so forward declare it. Alternatively, maybe these files should "#includeconfig.h".All of these problems go away if you don't insist on changing every single caller, you'll just have a step where you remove the current global in favor of some "config callback with kvi" info, and "make" will spot those callers that aren't converted yet.
Those changes will be trivial enough (just the callers I noted above) to not require the tricky cocci patch in 08/14.
Quoted 26 lines
* Likely deficiencies in .cocci patch
- submodule-config.c:gitmodules_cb()
Manually refactor a
parse_config()call that gets missed because it uses a different "*data" arg.-
grep.h, variousManually refactor
grep_config()calls. Not sure why these don't get picked up.- config.c:git_config_include(), http.c:http_options()
Manually add "kvi" where it was missed. Not sure why they get missed.
- builtin/clone.c:write_one_config()
Manually refactor a
git_clone_config()call. Probably got missed because I didn't includegit_config_parse_parameter().-
ident.hRemove the UNUSED attribute. Not sure why this is the only instance of this.
Quoted 7 lines
Quoted 5 lines
-
git-compat-util.h, compat/mingw.[h|c]Manually refactor
noop_core_config(),platform_core_config()andmingw_core_config(). I can probably add these as "manual fixups" in cocci.ditto.
Yeah, there was definitely more cocci trickery than I'd like. Btw, if you comments on the .cocci file itself, feel free to share. I obviously just hacked together something based on a very rudimentary understanding of cocci and I'd love suggestions on how to improve.
Re: [PATCH 10/14] (RFC-only) config: finish config_fn_t refactor
In reply to Jonathan TanI've covered most your response to Ævar upthread, so I'll omit that.
Quoted 7 lines · Jonathan Tan
As for my own opinions, (before Ævar sent this email) I took a look at these patches myself and had some issues with at least the first 2: in patch 1,
kvi_fn()replacesfn()for some but not all invocations offn()(in patch 2, you can see one such invocation that was not changed), and I was having difficulty thinking of what kind of bugs I should watch out for since not all invocations were changed; and in patch 2, the safeguard of not setting kvi and source together was
Quoted 8 lines
removed and likewise I was having difficulty thinking of what kind of bugs could occur from both being set at once inadvertently. I was going to suggest reordering the patches such that the large-scale refactoring (and any supporting patches like [PATCH 06/14] config: inline
git_color_default_config) should occur first (or waiting for a reviewer who is convinced that patches 1 and 2 are OK, I guess), but having now seen that sidestepping a large part of this makes sense, sidestepping seems like a good idea to me.
In an off-list discussion, we described some plausible ways to organize the refactor that would make it easier for a reviewer to confirm safety.
I haven't tried that yet because it sounds like you'd prefer the sidestepping approach. Do you prefer that primarily for safety reasons, or is it largely motivated by other concerns too (e.g. reducing churn or sidestepping produces a better API)? If the primary concern is just safety, I'm somewhat confident that we can find some way to organize this that makes it easier to review and I should just do it.
Re: [PATCH 10/14] (RFC-only) config: finish config_fn_t refactor
Quoted 1 line · Glen Choo
I've covered most your response to Ævar upthread, so I'll omit that.
Thanks. Indeed, I missed the situation in which a caller used kvi not by accessing its fields directly but by passing kvi to a function in config.c.
Quoted 9 lines
In an off-list discussion, we described some plausible ways to organize the refactor that would make it easier for a reviewer to confirm safety.
I haven't tried that yet because it sounds like you'd prefer the sidestepping approach. Do you prefer that primarily for safety reasons, or is it largely motivated by other concerns too (e.g. reducing churn or sidestepping produces a better API)? If the primary concern is just safety, I'm somewhat confident that we can find some way to organize this that makes it easier to review and I should just do it.
My preference for the sidestepping approach was to reduce churn, but as you have pointed out, it doesn't actually reduce churn. So now I think that the patches should be reordered (but am open to being convinced otherwise, of course).
As for safety and better API, I think both approaches (bulk modification of all functions to take the new config_fn_t and two sets of functions each taking a different function type) are equally safe, and it is bulk modification that results in a better API (as you've demonstrated, having kvi information is needed for good error messages, and I expect that to be more and more needed).
PATCH v2 1/14 config: inline git_color_default_config
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
git_color_default_config() is a shorthand for calling two other config callbacks. There are no other non-static functions that do this and it will complicate our refactoring of config_fn_t so inline it instead.
--- builtin/branch.c | 5 ++++- builtin/clean.c | 6 ++++-- builtin/grep.c | 5 ++++- builtin/show-branch.c | 5 ++++- builtin/tag.c | 6 +++++- color.c | 8 -------- color.h | 6 +----- 7 files changed, 22 insertions(+), 19 deletions(-)
builtin/branch.c +4 -1
@@ -114,7 +114,10 @@ static int git_branch_config(const char *var, const char *value, void *cb)return 0 ; } -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static const char *branch_get_color (enum color_branch ix)
builtin/clean.c +4 -2
@@ -129,8 +129,10 @@ static int git_clean_config(const char *var, const char *value, void *cb)return 0 ; } -/* inspect the color.ui config variable and others */ -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static const char *clean_get_color (enum color_clean ix)
builtin/grep.c +4 -1
@@ -290,7 +290,10 @@ static int wait_all(void)static int grep_cmd_config (const char *var,const char *value,void *cb) {int st =grep_config (var, value, cb); -if (git_color_default_config (var, value,NULL ) <0 ) + +if (git_color_config (var, value, cb) <0 ) + st =-1 ; +else if (git_default_config (var, value, cb) <0 ) st =-1 ;if (!strcmp (var,"grep.threads" )) {
builtin/show-branch.c +4 -1
@@ -576,7 +576,10 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)return 0 ; } -return git_color_default_config (var, value, cb); +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static int omit_in_dense (struct commit *commit,struct commit **rev,int n)
builtin/tag.c +5 -1
@@ -204,7 +204,11 @@ static int git_tag_config(const char *var, const char *value, void *cb)if (starts_with (var,"column." ))return git_column_config (var, value,"tag" , &colopts); -return git_color_default_config (var, value, cb); + +if (git_color_config (var, value, cb) <0 ) +return -1 ; + +return git_default_config (var, value, cb); }static void write_tag_body (int fd,const struct object_id *oid)
color.c +0 -8
@@ -427,14 +427,6 @@ int git_color_config(const char *var, const char *value, void *cb UNUSED)return 0 ; } -int git_color_default_config (const char *var,const char *value,void *cb) -{ -if (git_color_config (var, value, cb) <0 ) -return -1 ; - -return git_default_config (var, value, cb); -} -void color_print_strbuf (FILE *fp,const char *color,const struct strbuf *sb) {if (*color)
color.h +1 -5
@@ -88,12 +88,8 @@ extern const int column_colors_ansi_max;*/ extern int color_stdout_is_tty; -/* -* Use the first one if you need only color config; the second is a convenience -* if you are just going to change to git_default_config, too. -*/ +/* Parse color config. */ int git_color_config (const char *var,const char *value,void *cb); -int git_color_default_config (const char *var,const char *value,void *cb);/* * Parse a config option, which can be a boolean or one of
Signature · 1 line
gitgitgadget
PATCH v2 2/14 urlmatch.h: use config_fn_t type
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
These are actually used as config callbacks, so use the typedef-ed type and make future refactors easier.
--- urlmatch.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
urlmatch.h +3 -2
@@ -2,6 +2,7 @@#define URL_MATCH_H #include "string-list.h" +#include "config.h" struct url_info {/* normalized url on success, must be freed, otherwise NULL */
@@ -48,8 +49,8 @@ struct urlmatch_config {const char *key;void *cb; -int (*collect_fn)(const char *var,const char *value,void *cb); -int (*cascade_fn)(const char *var,const char *value,void *cb); +config_fn_t collect_fn; +config_fn_t cascade_fn;/* * Compare the two matches, the one just discovered and the existing * best match and return a negative value if the found item is to be
Signature · 1 line
gitgitgadget
PATCH v2 3/14 (RFC-only) config: add kvi arg to config_fn_t
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
..without actually changing any of its implementations. This commit does not build - I've split this out for readability, but post-RFC I will squash this with the rest of the refactor + cocci changes.
--- config.c | 8 +- config.h | 16 +- .../coccinelle/config_fn_kvi.pending.cocci | 146 ++++++++++++++++++ 3 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 contrib/coccinelle/config_fn_kvi.pending.cocci
config.c +4 -4
@@ -489,7 +489,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;
@@ -671,7 +671,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; }
@@ -959,7 +959,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;
@@ -2303,7 +2303,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);
config.h +8 -8
@@ -111,6 +111,13 @@ struct config_options { } error_action; }; +struct key_value_info { +const char *filename; +int linenr; +enum config_origin_type origin_type; +enum config_scope scope; +}; +/** * A config callback function takes three parameters: *
@@ -129,7 +136,7 @@ struct config_options {* A config callback should return 0 for success, or -1 if the variable * could not be parsed properly. */ -typedef int (*config_fn_t )(const char *,const char *,void *); +typedef int (*config_fn_t )(const char *,const char *,struct key_value_info *,void *);int git_default_config (const char *,const char *,void *);
@@ -667,13 +674,6 @@ int git_config_get_expiry(const char *key, const char **output);/* parse either "this many days" integer, or "5.days.ago" approxidate */ int git_config_get_expiry_in_days (const char *key,timestamp_t *,timestamp_t now); -struct key_value_info { -const char *filename; -int linenr; -enum config_origin_type origin_type; -enum config_scope scope; -}; -/** * First prints the error message specified by the caller in `err` and then * dies printing the line number and the file name of the highest priority
contrib/coccinelle/config_fn_kvi.pending.cocci new file +146 -0
146 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH v2 8/14 builtin/config.c: test misuse of format_config()
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
current_config_*() functions aren't meant to be called outside of config callbacks because they read state that is only set when iterating through config. However, several sites in builtin/config.c are indirectly calling these functions outside of config callbacks thanks to the format_config() helper. Show the current, bad behavior via tests so that the fixes in a subsequent commit will be clearer.
The misbehaving cases are:
* "git config --get-urlmatch --show-scope" results in an "unknown" scope, where it arguably should show the config file's scope. It's clear that this wasn't intended, though: 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.
* Similarly, "git config --default" doesn't set config source metadata , so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG().
[1] https://lore.kernel.org/git/[email protected]/
--- t/t1300-config.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
t/t1300-config.sh +25 -0
@@ -1627,6 +1627,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 && + unknown http.cookiefile /tmp/cookie.txt + unknown 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/"]
@@ -2014,6 +2029,10 @@ test_expect_success '--show-origin blob ref' ' test_cmp expect output ' +test_expect_success '--show-origin with --default' ' + test_must_fail git config --show-origin --default foo some.key +' + test_expect_success '--show-scope with --list' ' cat >expect <<-EOF && global user.global=true
@@ -2082,6 +2101,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 "unknown 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 &&
Signature · 1 line
gitgitgadget
v2 cover config: remove global state from config iteration
In reply to Glen Choo via GitGitGadgetThanks for the review on the previous round!
This v2 is mostly a reorganization of v1, largely based off Jonathan's feedback in [1]. As such, nearly all of v1's cover letter still applies (except for the "Patch Overview" section [2]) so this cover letter omits those bits that have already been covered. The first non-RFC version will get rerolled with full cover letter.
Since a lot of this series removes the config_reader stuff from gc/config-parsing-cleanup, it might be useful to diff this with "master" right before that:
git diff 0a8c337394 HEAD -- config.c
= Changes since v1
* Reorganize patches in a (hopefully) easier-to-review way.
* Squash bugs in builtin/config.c that became apparent during the refactor. These could have been fixed in v1, but they dropped off my radar.
= Patch overview
* 1-5/14 add the "kvi" parameter to the config_fn_t signature. These are mostly unchanged from v1.
* 6-11/14 converts the config.c machinery off "config_reader.config_kvi" and "config_reader.source" and onto the new "kvi" arg. Most of the changes from v1 are here.
In v1, we converted all of the config.c machinery first, making the "kvi" arg available everywhere before the refactor. Thus we could convert all callers of the current_*() API to the "kvi" arg in a single step. However (as Jonathan rightfully pointed out), some of the changes to the machinery are non-trivial, and it's quite difficult to spot bugs in the intermediate patches.
In v2, we convert the config.c machinery from "config_reader" to "kvi"
one-by-one: configsets, then files, then CLI. To exercise the "kvi" arg as soon as possible, we convert from current_*() to "kvi" as soon as it is available. For example, in 6/14 "kvi" is available only in configsets, so we convert the current_*() call sites that are only reached via configsets and leave the others untouched. This means that we have a mix of current_*() and "kvi" in the middle, but auditing the changes is relatively easy (compared to v1's machinery changes), since you only need to verify that a callback isn't relying on the "kvi" arg before it is available, and that current_*() and "kvi" give the same value.
* 8-9/14 squashes some bugs where builtin/config.c was calling the current_*() API outside of config callbacks. The "kvi" plumbing doesn't just make the bugs apparent, it also provides an obvious way to fix the bugs (by injecting "kvi" into the right places in builtin/config.c). These would have been nontrivial to fix if we were still using global state.
* 12-14/14 remove config_reader by taking advantage of the "kvi" parameter and doing some other light plumbing.
[1]
https://lore.kernel.org/git/[email protected]
[2]
https://lore.kernel.org/[email protected]
Glen Choo (14):
config: inline git_color_default_config
urlmatch.h: use config_fn_t type
(RFC-only) config: add kvi arg to config_fn_t (RFC-only) config: apply cocci to config_fn_t implementations (RFC-only) config: finish config_fn_t refactor config.c: pass kvi in configsets
config: provide kvi with config files builtin/config.c: test misuse of format_config() config.c: provide kvi with CLI config
trace2: plumb config kvi
config: pass kvi to die_bad_number()
config.c: remove config_reader from configsets
config: add kvi.path, use it to evaluate includes
config: pass source to config_parser_event_fn_t
alias.c | 3 +- archive-tar.c | 5 +- archive-zip.c | 1 + builtin/add.c | 5 +- builtin/blame.c | 5 +- builtin/branch.c | 8 +- builtin/cat-file.c | 5 +- builtin/checkout.c | 7 +- builtin/clean.c | 9 +- builtin/clone.c | 10 +- builtin/column.c | 3 +- builtin/commit-graph.c | 3 +- builtin/commit.c | 20 +- builtin/config.c | 65 ++- builtin/difftool.c | 5 +- builtin/fetch.c | 12 +- builtin/fsmonitor--daemon.c | 11 +- builtin/grep.c | 12 +- builtin/help.c | 5 +- builtin/index-pack.c | 9 +- builtin/log.c | 12 +- builtin/merge.c | 7 +- builtin/multi-pack-index.c | 1 + builtin/pack-objects.c | 19 +- builtin/patch-id.c | 5 +- builtin/pull.c | 5 +- builtin/push.c | 5 +- builtin/read-tree.c | 5 +- builtin/rebase.c | 5 +- builtin/receive-pack.c | 15 +- builtin/reflog.c | 7 +- builtin/remote.c | 12 +- builtin/repack.c | 5 +- builtin/reset.c | 5 +- builtin/send-pack.c | 5 +- builtin/show-branch.c | 8 +- builtin/stash.c | 5 +- builtin/submodule--helper.c | 3 +- builtin/tag.c | 9 +- builtin/var.c | 5 +- builtin/worktree.c | 5 +- bundle-uri.c | 9 +- color.c | 8 - color.h | 6 +- compat/mingw.c | 3 +- compat/mingw.h | 4 +- config.c | 538 +++++++----------- config.h | 54 +- connect.c | 4 +- .../coccinelle/config_fn_kvi.pending.cocci | 146 +++++ contrib/coccinelle/git_config_number.cocci | 27 + convert.c | 4 +- credential.c | 1 + delta-islands.c | 3 +- diff.c | 19 +- diff.h | 7 +- fetch-pack.c | 5 +- fmt-merge-msg.c | 7 +- fmt-merge-msg.h | 3 +- fsck.c | 11 +- fsck.h | 4 +- git-compat-util.h | 2 + gpg-interface.c | 6 +- grep.c | 7 +- grep.h | 4 +- help.c | 10 +- http.c | 15 +- ident.c | 3 +- ident.h | 4 +- imap-send.c | 7 +- ll-merge.c | 1 + ls-refs.c | 2 +- mailinfo.c | 5 +- notes-utils.c | 3 +- notes.c | 3 +- pager.c | 5 +- pretty.c | 1 + promisor-remote.c | 4 +- remote.c | 7 +- revision.c | 3 +- scalar.c | 3 +- sequencer.c | 28 +- setup.c | 17 +- submodule-config.c | 31 +- submodule-config.h | 3 +- t/helper/test-config.c | 21 +- t/helper/test-userdiff.c | 4 +- t/t1300-config.sh | 27 + trace2.c | 4 +- trace2.h | 3 +- trace2/tr2_cfg.c | 12 +- trace2/tr2_sysenv.c | 3 +- trace2/tr2_tgt.h | 4 +- trace2/tr2_tgt_event.c | 4 +- trace2/tr2_tgt_normal.c | 4 +- trace2/tr2_tgt_perf.c | 4 +- trailer.c | 2 + upload-pack.c | 18 +- urlmatch.c | 7 +- urlmatch.h | 8 +- worktree.c | 2 +- xdiff-interface.c | 5 +- xdiff-interface.h | 5 +- 103 files changed, 883 insertions(+), 642 deletions(-) create mode 100644 contrib/coccinelle/config_fn_kvi.pending.cocci create mode 100644 contrib/coccinelle/git_config_number.cocci
base-commit: 9857273be005833c71e2d16ba48e193113e12276
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1497%2Fchooglen%2Fconfig%2Fno-global-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1497/chooglen/config/no-global-v2
Pull-Request: https://github.com/git/git/pull/1497
Range-diff vs v1:
1: 49bc2f6eedc < -: ----------- config.c: introduce kvi_fn(), use it for configsets
6: cb021810688 = 1: d5edf7e3fdd config: inline git_color_default_config
7: e0f43eafa07 = 2: 821f0b90580 urlmatch.h: use config_fn_t type
8: 961d06f89cb ! 3: 6834e37066e (RFC-only) config: add kvi arg to config_fn_t
@@ Commit message
Signed-off-by: Glen Choo <[email protected]>
## config.c ##
-@@ config.c: static int kvi_fn(config_fn_t fn, const char *key, const char *value,
- {
- int ret;
- config_reader_push_kvi(&the_reader, kvi);
-- ret = fn(key, value, data);
-+ ret = fn(key, value, kvi, data);
- config_reader_pop_kvi(&the_reader);
+@@ config.c: 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;
+
+@@ config.c: 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;
}
+@@ config.c: 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;
+@@ config.c: 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);
## config.h ##
@@ config.h: struct config_options {
@@ config.h: struct config_options {
+ int linenr;
+ enum config_origin_type origin_type;
+ enum config_scope scope;
-+ const char *path;
-+ struct key_value_info *prev;
+};
+
/**
@@ config.h: int git_config_get_expiry(const char *key, const char **output);
- int linenr;
- enum config_origin_type origin_type;
- enum config_scope scope;
-- const char *path;
-- struct key_value_info *prev;
-};
-
/** 9: 5eb3874b494 ! 4: bd52c6232ec (RFC-only) config: apply cocci to config_fn_t implementations
@@ config.c: static void populate_remote_urls(struct config_include_data *inc)
void *data UNUSED)
{
const char *remote_name;
-@@ config.c: static int include_condition_is_true(struct key_value_info *kvi, +@@ config.c: static int include_condition_is_true(struct config_source *cs,
+ return 0;
+ }
- static int kvi_fn(config_fn_t fn, const char *key, const char *value,
- struct key_value_info *kvi, void *data);
-static int git_config_include(const char *var, const char *value, void *data) +static int git_config_include(const char *var, const char *value,
+ struct key_value_info *kvi UNUSED, void *data)
{
struct config_include_data *inc = data;
- struct key_value_info *kvi = inc->config_reader->config_kvi;
+ struct config_source *cs = inc->config_reader->source;
@@ config.c: int git_config_color(char *dest, const char *var, const char *value)
return 0;
}
@@ config.c: struct configset_add_data {
{
struct configset_add_data *data = cb; configset_add_value(data->config_reader, data->config_set, key, value);
-@@ config.c: static int store_aux_event(enum config_event_t type, size_t begin, size_t end, +@@ config.c: static int store_aux_event(enum config_event_t type,
return 0;
}
10: 1071e70c928 ! 5: f363b160259 (RFC-only) config: finish config_fn_t refactor
@@ Commit message
refactoring away, since git_xmerge_config() can call git_default_config().
- - config.c:git_config_include()
-
- Replace the local "kvi" variable with the "kvi" parameter. This
- makes config_include_data.config_reader obsolete, so remove it.
-
* Hard for cocci to catch
- urlmatch.c
@@ compat/mingw.h: typedef _sigset_t sigset_t;
/*
- ## config.c ##
-@@ config.c: struct config_include_data {
- void *data;
- const struct config_options *opts;
- struct git_config_source *config_source;
-- struct config_reader *config_reader;
-
- /*
- * All remote URLs discovered when reading all config files.
-@@ config.c: static int include_condition_is_true(struct key_value_info *kvi,
- static int kvi_fn(config_fn_t fn, const char *key, const char *value,
- struct key_value_info *kvi, void *data);
- static int git_config_include(const char *var, const char *value,
-- struct key_value_info *kvi UNUSED, void *data)
-+ struct key_value_info *kvi, void *data)
- {
- struct config_include_data *inc = data;
-- struct key_value_info *kvi = inc->config_reader->config_kvi;
- const char *cond, *key;
- size_t cond_len;
- int ret;
-@@ config.c: int config_with_options(config_fn_t fn, void *data,
- inc.data = data;
- inc.opts = opts;
- inc.config_source = config_source;
-- inc.config_reader = &the_reader;
- fn = git_config_include;
- data = &inc;
- }
-
## diff.h ##
@@ diff.h: void free_diffstat_info(struct diffstat_t *diffstat);
int parse_long_opt(const char *opt, const char **argv,
11: b38653477c7 ! 6: f57c1007cad config: remove current_config_(line|name|origin_type)
@@ Metadata
Author: Glen Choo <[email protected]>
## Commit message ##
- config: remove current_config_(line|name|origin_type)
+ config.c: pass kvi in configsets
- Trivially replace current_config_(line|name|origin_type) by reading the
- corresponding values from "struct key_value_info". This includes some
- light "kvi" plumbing for builtin/config.c, and for *origin_type,
- splitting out a function that turns "enum config_origin_type" into the
- human-readable string that callbacks actually want.
+ Trivially pass "struct key_value_info" to config callbacks in
+ configset_iter(). Then, in config callbacks that are only used with
+ configsets, use the "kvi" arg to replace calls to current_config_*(),
+ and delete current_config_line() because it has no remaining callers.
- Signed-off-by: Glen Choo <[email protected]>
+ This leaves builtin/config.c and config.c as the only remaining users of
+ current_config_*().
- ## builtin/config.c ##
-@@ builtin/config.c: 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(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);
- }
-
-@@ builtin/config.c: static void show_config_scope(struct strbuf *buf)
- }
-
- static int show_all_config(const char *key_, const char *value_,
-- struct key_value_info *kvi UNUSED, void *cb UNUSED)
-+ struct key_value_info *kvi, void *cb UNUSED)
- {
- if (show_origin || show_scope) {
- struct strbuf buf = STRBUF_INIT;
- if (show_scope)
- show_config_scope(&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);
-@@ builtin/config.c: 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_,
-+ struct key_value_info *kvi)
- {
- if (show_scope)
- show_config_scope(buf);
- if (show_origin)
-- show_config_origin(buf);
-+ show_config_origin(kvi, buf);
- if (show_keys)
- strbuf_addstr(buf, key_);
- if (!omit_values) {
-@@ builtin/config.c: static int format_config(struct strbuf *buf, const char *key_, const char *value
- }
-
- static int collect_config(const char *key_, const char *value_,
-- struct key_value_info *kvi UNUSED, void *cb)
-+ struct key_value_info *kvi, void *cb)
- {
- struct strbuf_list *values = cb;
-
-@@ builtin/config.c: 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)
-@@ builtin/config.c: static int get_value(const char *key_, const char *regex_, unsigned flags)
- 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, NULL) < 0)
- die(_("failed to format default config value: %s"),
- default_value);
- }
-@@ builtin/config.c: 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, NULL);
- fwrite(buf.buf, 1, buf.len, stdout);
- strbuf_release(&buf);
-
+ Signed-off-by: Glen Choo <[email protected]>
## builtin/remote.c ##
@@ builtin/remote.c: struct push_default_info
@@ builtin/remote.c: struct push_default_info
{
struct push_default_info* info = cb;
if (strcmp(key, "remote.pushdefault") ||
-@@ builtin/remote.c: static int config_read_push_default(const char *key, const char *value,
+ !value || strcmp(value, info->old_name))
+ return 0;
- info->scope = current_config_scope();
+- 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, kvi->filename);
++ strbuf_addstr(&info->origin, config_origin_type_name(kvi->origin_type));
+ info->linenr = kvi->linenr;
return 0;
}
## config.c ##
+@@ config.c: 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 key_value_info *kvi;
+
+ for (i = 0; i < list->nr; i++) {
+ entry = list->items[i].e;
+ value_index = list->items[i].value_index;
+ values = &entry->value_list;
++ kvi = values->items[value_index].util;
+
+ config_reader_set_kvi(reader, values->items[value_index].util);
+
+- 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);
+-
++ if (fn(entry->key, values->items[value_index].string, kvi, data) < 0)
++ git_die_config_linenr(entry->key, kvi->filename, kvi->linenr);
+ config_reader_set_kvi(reader, NULL);
+ }
+ }
@@ config.c: static int reader_origin_type(struct config_reader *reader,
return 0;
}
@@ config.c: static int reader_origin_type(struct config_reader *reader,
switch (type) {
case CONFIG_ORIGIN_BLOB:
return "blob";
-@@ config.c: static int reader_config_name(struct config_reader *reader, const char **out)
- return 0;
+@@ config.c: const char *current_config_origin_type(void)
+ }
}
--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) ++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) {
- if (the_reader.config_kvi)
+ switch (scope) {
@@ config.c: enum config_scope current_config_scope(void)
- return CONFIG_SCOPE_UNKNOWN;
+ return the_reader.parsing_scope;
}
-int current_config_line(void)
@@ config.c: enum config_scope current_config_scope(void)
- if (the_reader.config_kvi)
- return the_reader.config_kvi->linenr;
- else
-- BUG("current_config_line called outside config callback");
+- return the_reader.source->linenr;
-}
-
int lookup_config(const char **mapping, int nr_mapping, const char *var)
@@ config.c: enum config_scope current_config_scope(void)
int i;
## config.h ##
-@@ config.h: void git_global_config(char **user, char **xdg);
- int git_config_parse_parameter(const char *, config_fn_t fn, void *data); -
+@@ config.h: 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 *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:
+ ## remote.c ##
+@@ remote.c: static void read_branches_file(struct remote_state *remote_state,
+ }
+
+ static int handle_config(const char *key, const char *value,
+- struct key_value_info *kvi UNUSED, void *cb)
++ struct key_value_info *kvi, void *cb)
+ {
+ const char *name;
+ size_t namelen;
+@@ remote.c: 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);
+
## t/helper/test-config.c ##
@@
*/
@@ t/helper/test-config.c: static int iterate_cb(const char *var, const char *value
- 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(current_config_scope()));
++ printf("scope=%s\n", config_scope_name(kvi->scope));
return 0;
+ }
3: 8c7a84137c8 ! 7: 641a56f0b40 config: use kvi for config files
@@ Metadata
Author: Glen Choo <[email protected]>
## Commit message ##
- config: use kvi for config files
+ config: provide kvi with config files
- Plumb "struct key_value_info" and use "kvi_fn()" when parsing config
- files. As a result, "config_reader.kvi" is now always set correctly, so
- we can remove "config_reader.scope" (but not the ".source" member since
- that's still needed by some non-parsing machinery). This requires
- plumbing an additional "enum config_scope" arg through
- "git_config_from_file_with_options()" and the underlying machinery to
- make up for the fact that "struct key_value_info" has a ".scope" member,
- but "struct config_source" does not.
+ Refactor out the configset logic that caches "struct config_source" and
+ "enum config_scope" as a "struct key_value_info", and use it to pass the
+ "kvi" arg to config callbacks when parsing config files. Get the "enum
+ config_scope" value by plumbing an additional arg through
+ git_config_from_file_with_options() and the underlying machinery.
- To handle "include" directives correctly, use push/pop semantics for
- "config_reader.config_kvi" (instead of "set" semantics) like we do for
- "config_reader.source". Otherwise, "config_reader.config_kvi" won't be
- set correctly when we finish parsing an included config file and we want
- to "pop" it to resume parsing the original file. This distinction only
- matters while there is a global "kvi", i.e. it will be obsolete at the
- end of the series.
+ We do not exercise the "kvi" arg 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 "kvi" yet.
@@ bundle-uri.c: int bundle_uri_parse_config_format(const char *uri,
if (!result && list->mode == BUNDLE_MODE_NONE) {
## config.c ##
-@@ config.c: 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 -@@ config.c: 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)
-+static inline void config_reader_push_kvi(struct config_reader *reader,
-+ struct key_value_info *kvi)
- {
-+ kvi->prev = reader->config_kvi;
- reader->config_kvi = kvi;
- }
-
--static inline void config_reader_set_scope(struct config_reader *reader,
-- enum config_scope scope)
-+static inline struct key_value_info *config_reader_pop_kvi(struct config_reader *reader)
- {
-- reader->parsing_scope = scope;
-+ struct key_value_info *ret;
-+ if (!reader->config_kvi)
-+ BUG("tried to pop config_kvi, but we weren't reading config");
-+ ret = reader->config_kvi;
-+ reader->config_kvi = reader->config_kvi->prev;
-+ return ret;
- }
-
- static int pack_compression_seen;
@@ config.c: static int handle_path_include(struct config_source *cs, const char *path,
!cs ? "<unknown>" :
cs->name ? cs->name :
@@ config.c: static int handle_path_include(struct config_source *cs, const char *p
inc->depth--;
}
cleanup:
-@@ config.c: 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, &opts);
--
-- config_reader_set_scope(inc->config_reader, store_scope);
- }
-
- static int forbid_remote_url(const char *var, const char *value UNUSED,
@@ config.c: static int include_condition_is_true(struct config_source *cs,
- return 0;
}
-+static int kvi_fn(config_fn_t fn, const char *key, const char *value,
-+ struct key_value_info *kvi, void *data);
- static int git_config_include(const char *var, const char *value, void *data)
+ static int git_config_include(const char *var, const char *value,
+- struct key_value_info *kvi UNUSED, void *data)
++ struct key_value_info *kvi, void *data)
{
struct config_include_data *inc = data;
struct config_source *cs = inc->config_reader->source;
-+ struct key_value_info *kvi = inc->config_reader->config_kvi;
- const char *cond, *key;
- size_t cond_len;
- int ret;
-@@ config.c: static int git_config_include(const char *var, const char *value, void *data) +@@ config.c: 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, inc->data);
-+ ret = kvi_fn(inc->fn, var, value, kvi, inc->data);
+- ret = inc->fn(var, value, NULL, inc->data);
++ ret = inc->fn(var, value, kvi, inc->data);
if (ret < 0)
return ret;
-@@ config.c: out_free_ret_1:
- }
-
- static int kvi_fn(config_fn_t fn, const char *key, const char *value,
-- struct key_value_info *kvi,
-- void *data)
-+ struct key_value_info *kvi, void *data)
- {
- int ret;
-- config_reader_set_kvi(&the_reader, kvi);
-+ config_reader_push_kvi(&the_reader, kvi);
- ret = fn(key, value, data);
-- config_reader_set_kvi(&the_reader, NULL);
-+ config_reader_pop_kvi(&the_reader);
- return ret;
- }
-
@@ config.c: static char *parse_value(struct config_source *cs)
}
}
@@ config.c: static int get_value(struct config_source *cs, config_fn_t fn, void *d
* accurate line number in error messages.
*/
cs->linenr--;
-- ret = fn(name->buf, value, data);
+- ret = fn(name->buf, value, NULL, data);
+ kvi->linenr = cs->linenr;
-+ ret = kvi_fn(fn, name->buf, value, kvi, data);
++ ret = fn(name->buf, value, kvi, data);
if (ret >= 0)
cs->linenr++;
return ret;
@@ config.c: static int git_parse_source(struct config_source *cs, config_fn_t fn,
break;
}
-@@ config.c: int git_default_config(const char *var, const char *value, void *cb) +@@ config.c: int git_default_config(const char *var, const char *value,
* this function.
*/
static int do_config_from(struct config_reader *reader,
@@ config.c: static int do_config_from_file(struct config_reader *reader,
- ret = do_config_from(reader, &top, fn, data, opts);
+ ret = do_config_from(reader, &top, fn, data, scope, opts);
funlockfile(f);
-+
return ret;
}
@@ config.c: int git_config_from_blob_oid(config_fn_t fn,
}
char *git_system_config(void)
-@@ config.c: 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,
- config_fn_t fn, void *data)
- {
- int ret = 0;
@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
- char *xdg_config = NULL;
- char *user_config = NULL;
- char *repo_config;
-- enum config_scope prev_parsing_scope = reader->parsing_scope;
-
- if (opts->commondir)
- repo_config = mkpathdup("%s/config", opts->commondir);
-@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
- else
- repo_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))
@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
+ data, CONFIG_SCOPE_SYSTEM,
+ NULL);
-- config_reader_set_scope(reader, CONFIG_SCOPE_GLOBAL);
+ 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))
@@ config.c: 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);
+ 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);
+ config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE);
if (!opts->ignore_worktree && repository_format_worktree_config) {
char *path = git_pathdup("config.worktree");
if (!access_or_die(path, R_OK, 0))
@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
free(path);
}
-- config_reader_set_scope(reader, 0);
- 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);
-@@ config.c: 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) {
@@ config.c: 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.
*/
if (config_source && config_source->use_stdin) {
@@ config.c: int config_with_options(config_fn_t fn, void *data,
- data);
+ data, config_source->scope);
} else {
-- ret = do_git_config_sequence(&the_reader, opts, fn, data);
-+ ret = do_git_config_sequence(opts, fn, data);
- }
-
- if (inc.remote_urls) {
- string_list_clear(inc.remote_urls, 0);
- FREE_AND_NULL(inc.remote_urls);
+ ret = do_git_config_sequence(&the_reader, opts, fn, data);
}
-- config_reader_set_scope(&the_reader, prev_scope);
- return ret;
- }
-
@@ config.c: static int configset_add_value(struct config_reader *reader,
- l_item->e = e;
- l_item->value_index = e->value_list.nr - 1;
-
-- if (reader->source && reader->source->name) {
+ 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;
-- kv_info->scope = reader->parsing_scope;
-- } else
-- kvi_from_param(kv_info);
-+ memcpy(kv_info, reader->config_kvi, sizeof(struct key_value_info));
++ 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;
@@ config.c: int git_config_set_multivar_in_file_gently(const char *config_filename
error(_("invalid config file %s"), config_filename); ret = CONFIG_INVALID_FILE;
goto out_free;
-@@ config.c: enum config_scope current_config_scope(void)
- if (the_reader.config_kvi)
- return the_reader.config_kvi->scope;
- else
-- return the_reader.parsing_scope;
-+ /*
-+ * FIXME This should be a BUG, but tr2_list_env_vars_fl is
-+ * calling this outside of a config callback. This will be
-+ * easier to fix when we plumb kvi through the config callbacks,
-+ * so leave this untouched for now.
-+ */
-+ return CONFIG_SCOPE_UNKNOWN;
- }
-
- int current_config_line(void)
## config.h ##
-@@ config.h: int git_default_config(const char *, const char *, void *); +@@ config.h: int git_default_config(const char *, const char *, struct key_value_info *,
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 *,
@@ config.h: int git_default_config(const char *, const char *, void *);
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);
-@@ config.h: struct key_value_info {
- int linenr;
- enum config_origin_type origin_type;
- enum config_scope scope;
-+ struct key_value_info *prev;
- };
-
- /**
## fsck.c ##
@@ fsck.c: static int fsck_blob(const struct object_id *oid, const char *buf,
-: ----------- > 8: 74f43fc727e builtin/config.c: test misuse of format_config() 2: a682612cff2 ! 9: 3760015d2c0 config.c: use kvi for CLI config
@@ Metadata
Author: Glen Choo <[email protected]>
## Commit message ##
- config.c: use kvi for CLI config
+ config.c: provide kvi with CLI config
- Plumb "struct key_value_info" and use "kvi_fn()" when parsing CLI
- config. Do this by refactoring out and reusing the logic that sets the
- "struct key_value_info" members when caching CLI config in a configset.
+ Refactor out kvi_from_param() from the logic that caches CLI config in
+ configsets, and use it to pass the "kvi" arg to config callbacks when
+ parsing CLI config. Now that "kvi" is always present when config
+ machinery calls config callbacks, plumb "kvi" so that we can replace
+ nearly all calls to current_config_*(). (The exception is an edge case
+ where trace2/*.c calls current_config_scope(). That will be handled in a
+ later commit.) 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().
- This lets us get rid of the fake "struct config_source" in
- "git_config_from_parameters()", so we now only have to maintain one
- implementation. Additionally, this plumbing also reveals that
- "git_config_parse_parameter()" hasn't been setting either
- "the_reader.source" or "the_reader.config_kvi", so any calls to
- "current_*" would either BUG() or return *_UNKNOWN values.
+ Plumbing "kvi" reveals a few places where we've been doing the wrong
+ thing:
- Also, get rid of the BUG() checks that forbid setting ".config_kvi" and
- ".source" at the same time, since we will run afoul of that check. They
- will soon be unnecessary when we remove ".source".
+ * git_config_parse_parameter() hasn't been setting config source
+ information, so plumb "kvi" there too.
+
+ * "git config --get-urlmatch --show-scope" iterates config to collect
+ values, but then attempts to display the scope after config iteration.
+ Fix this by copying the "kvi" arg 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" (we don't allow this combination of args
+ because of this bug), but that is left unchanged for now.
+
+ * "git config --default" doesn't have config source metadata when
+ displaying the default value. 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().
- ## config.c ##
-@@ config.c: static struct config_reader the_reader;
- static inline void config_reader_push_source(struct config_reader *reader,
- struct config_source *top)
+ ## builtin/config.c ##
+@@ builtin/config.c: 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(struct key_value_info *kvi, struct strbuf *buf)
{
-- if (reader->config_kvi)
-- BUG("source should not be set while iterating a config set");
- top->prev = reader->source;
- reader->source = top;
+ 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);
}
-@@ config.c: 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)
+
+-static void show_config_scope(struct strbuf *buf)
++static void show_config_scope(struct key_value_info *kvi, struct strbuf *buf)
{
-- if (kvi && (reader->source || reader->parsing_scope))
-- BUG("kvi should not be set while parsing a config source");
- reader->config_kvi = kvi;
+ 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 inline void config_reader_set_scope(struct config_reader *reader,
- enum config_scope scope)
+ static int show_all_config(const char *key_, const char *value_,
+- struct key_value_info *kvi UNUSED, void *cb UNUSED)
++ struct key_value_info *kvi, void *cb UNUSED)
+ {
+ 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);
+@@ builtin/config.c: 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_, struct key_value_info *kvi)
{
-- if (scope && reader->config_kvi)
-- BUG("scope should only be set when iterating through a config source");
- reader->parsing_scope = scope;
+ 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) {
+@@ builtin/config.c: static int format_config(struct strbuf *buf, const char *key_, const char *value
}
-@@ config.c: static int kvi_fn(config_fn_t fn, const char *key, const char *value,
+ static int collect_config(const char *key_, const char *value_,
+- struct key_value_info *kvi UNUSED, void *cb)
++ struct key_value_info *kvi, void *cb)
+ {
+ struct strbuf_list *values = cb;
+
+@@ builtin/config.c: 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)
+@@ builtin/config.c: static int get_value(const char *key_, const char *regex_, unsigned flags)
+ &given_config_source, &config_options);
+
+ if (!values.nr && default_value) {
++ struct key_value_info kvi = { 0 };
+ 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);
+ }
+@@ builtin/config.c: 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,
+- struct key_value_info *kvi UNUSED, void *cb)
++ struct key_value_info *kvi, void *cb)
+ {
+ struct string_list *values = cb;
+ struct string_list_item *item = string_list_insert(values, var);
+@@ builtin/config.c: static int urlmatch_collect_fn(const char *var, const char *value,
+ } else {
+ strbuf_reset(&matched->value);
+ }
++ memcpy(&matched->kvi, kvi, sizeof(struct key_value_info));
+
+ if (value) {
+ strbuf_addstr(&matched->value, value);
+@@ builtin/config.c: 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);
+
+
+ ## config.c ##
+@@ config.c: 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,
++ struct key_value_info *kvi,
++ const char *path,
+ struct config_include_data *inc)
+ {
+ int ret = 0;
+@@ config.c: 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:
+@@ config.c: 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, kvi, value, inc);
+
+ if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
+ cond && include_condition_is_true(cs, inc, cond, cond_len) &&
+@@ config.c: 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, kvi, value, inc);
+ inc->fn = old_fn;
+ }
+
+@@ config.c: out_free_ret_1:
}
static int config_parse_pair(const char *key, const char *value,
@@ config.c: 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 = (kvi_fn(fn, canonical_name, value, kvi, data) < 0) ? -1 : 0;
+- ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0;
++ ret = (fn(canonical_name, value, kvi, data) < 0) ? -1 : 0;
free(canonical_name);
return ret;
}
+
+/* for values read from git_config_from_parameters() */
-+static void kvi_from_param(struct key_value_info *out)
++void kvi_from_param(struct key_value_info *out)
+{
+ out->filename = NULL;
+ out->linenr = -1;
@@ config.c: static int parse_config_env_list(char *env, config_fn_t fn, void *data
}
else {
@@ config.c: 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;
--
-- source.origin_type = CONFIG_ORIGIN_CMDLINE;
-- config_reader_push_source(&the_reader, &source);
+ struct config_source source = CONFIG_SOURCE_INIT;
+ struct key_value_info kvi = { 0 };
+ 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;
@@ config.c: int git_config_from_parameters(config_fn_t fn, void *data)
ret = -1;
goto out;
}
-@@ config.c: out:
- strbuf_release(&envvar);
- strvec_clear(&to_free);
- free(envw);
-- config_reader_pop_source(&the_reader);
- return ret;
+@@ config.c: static int configset_find_element(struct config_set *set, const char *key,
+ return 0;
}
-@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
- free(path);
- }
-
-- config_reader_set_scope(reader, CONFIG_SCOPE_COMMAND);
-+ config_reader_set_scope(reader, 0);
- if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
- die(_("unable to parse command-line config"));
-
+-static int configset_add_value(struct config_reader *reader, ++static int configset_add_value(struct key_value_info *kvi_p,
++ struct config_reader *reader,
+ struct config_set *set, const char *key,
+ const char *value)
+ {
@@ config.c: static int configset_add_value(struct config_reader *reader,
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) {
-+ if (reader->source && reader->source->name) {
- kv_info->filename = strintern(reader->source->name);
- kv_info->linenr = reader->source->linenr;
- kv_info->origin_type = reader->source->origin_type;
-- } else {
+ 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;
-+ kv_info->scope = reader->parsing_scope;
-+ } else
+- kv_info->scope = reader->parsing_scope;
+ kvi_from_param(kv_info);
+ }
si->util = kv_info;
+@@ config.c: struct configset_add_data {
+ #define CONFIGSET_ADD_INIT { 0 }
+
+ static int config_set_callback(const char *key, const char *value,
+- struct key_value_info *kvi UNUSED, void *cb)
++ struct key_value_info *kvi, void *cb)
+ {
+ struct configset_add_data *data = cb;
+- configset_add_value(data->config_reader, data->config_set, key, value);
++ configset_add_value(kvi, data->config_reader, data->config_set, key, value);
+ return 0;
+ }
+
+@@ config.c: 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) {
+@@ config.c: 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)
+
+ ## config.h ##
+@@ config.h: 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:
+
+ ## t/t1300-config.sh ##
+@@ t/t1300-config.sh: test_expect_success 'urlmatch with --show-scope' '
+ EOF
+
+ cat >expect <<-EOF &&
+- unknown http.cookiefile /tmp/cookie.txt
+- unknown http.sslverify false
++ 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
+@@ t/t1300-config.sh: test_expect_success '--show-origin blob ref' '
+ '
+
+ test_expect_success '--show-origin with --default' '
+- test_must_fail git config --show-origin --default foo some.key
++ 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' '
+@@ t/t1300-config.sh: test_expect_success '--show-scope with --show-origin' ' +
+ test_expect_success '--show-scope with --default' '
+ git config --show-scope --default foo some.key >actual &&
+- echo "unknown foo" >expect &&
++ echo "command foo" >expect &&
+ test_cmp expect actual
+ '
+
12: 4723ae3bde6 ! 10: 7dc0c46b864 config: remove current_config_scope()
@@ Metadata
Author: Glen Choo <[email protected]>
## Commit message ##
- config: remove current_config_scope()
+ trace2: plumb config kvi
- Replace current_config_scope() by reading the corresponding value off
- "struct key_value_info".
-
- Most instances of this are trivial, except for the trace2/* files. 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
+ 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
@@ Commit message
information.
Teach tr2_list_env_vars_fl() to be well-behaved by using
- kvi_from_param(), which is already used internally by config.c for
- CLI/environment variable-based config.
+ 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.
- ## builtin/config.c ##
-@@ builtin/config.c: static void show_config_origin(struct key_value_info *kvi, struct strbuf *buf)
- strbuf_addch(buf, term);
+ ## config.c ##
+@@ config.c: 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 +@@ config.c: 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 void show_config_scope(struct strbuf *buf)
-+static void show_config_scope(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);
-@@ builtin/config.c: static int show_all_config(const char *key_, const char *value_,
- 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(kvi, &buf);
- /* Use fwrite as "buf" can contain \0's if "end_null" is set. */
-@@ builtin/config.c: static int format_config(struct strbuf *buf, const char *key_, const char *value
- struct key_value_info *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;
+
+@@ config.c: static void populate_remote_urls(struct config_include_data *inc)
{
- if (show_scope)
-- show_config_scope(buf);
-+ show_config_scope(kvi, buf);
- if (show_origin)
- show_config_origin(kvi, buf);
- if (show_keys)
-
- ## builtin/remote.c ##
-@@ builtin/remote.c: static int config_read_push_default(const char *key, const char *value,
- !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, kvi->filename);
- info->linenr = kvi->linenr;
-
- ## config.c ##
-@@ config.c: static int config_parse_pair(const char *key, const char *value,
+ 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, &opts);
+-
+- config_reader_set_scope(inc->config_reader, store_scope);
+ }
+
+ static int forbid_remote_url(const char *var, const char *value UNUSED,
+@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
+ char *xdg_config = NULL;
+ char *user_config = NULL;
+ char *repo_config;
+- enum config_scope prev_parsing_scope = reader->parsing_scope;
+
+ if (opts->commondir)
+ repo_config = mkpathdup("%s/config", opts->commondir);
+@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
+ else
+ repo_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))
+@@ config.c: 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))
+@@ config.c: 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);
- /* for values read from git_config_from_parameters() */
--static void kvi_from_param(struct key_value_info *out)
-+void kvi_from_param(struct key_value_info *out)
+- 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 && repository_format_worktree_config) {
+ char *path = git_pathdup("config.worktree");
+ if (!access_or_die(path, R_OK, 0))
+@@ config.c: static int do_git_config_sequence(struct config_reader *reader,
+ free(path);
+ }
+
+- 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);
+@@ config.c: int config_with_options(config_fn_t fn, void *data,
+ const struct config_options *opts)
{
- out->filename = NULL;
- out->linenr = -1;
+ struct config_include_data inc = CONFIG_INCLUDE_INIT;
+- enum config_scope prev_scope = the_reader.parsing_scope;
+ int ret;
+
+ if (opts->respect_includes) {
+@@ config.c: 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.
+@@ config.c: 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;
+ }
+
@@ config.c: static int reader_config_name(struct config_reader *reader, const char **out)
return 0;
}
@@ config.c: static int reader_config_name(struct config_reader *reader, const char
- if (the_reader.config_kvi)
- return the_reader.config_kvi->scope;
- else
-- /*
-- * FIXME This should be a BUG, but tr2_list_env_vars_fl is
-- * calling this outside of a config callback. This will be
-- * easier to fix when we plumb kvi through the config callbacks,
-- * so leave this untouched for now.
-- */
-- return CONFIG_SCOPE_UNKNOWN;
+- return the_reader.parsing_scope;
-}
-
int lookup_config(const char **mapping, int nr_mapping, const char *var)
@@ config.h: void git_global_config(char **user, char **xdg);
-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);
- /*
-@@ config.h: NORETURN void git_die_config_linenr(const char *key, const char *filename, int l
- lookup_config(mapping, ARRAY_SIZE(mapping), var)
- int lookup_config(const char **mapping, int nr_mapping, const char *var);
-
-+void kvi_from_param(struct key_value_info *out);
-+
- #endif /* CONFIG_H */
-
- ## remote.c ##
-@@ remote.c: static void read_branches_file(struct remote_state *remote_state,
- }
-
- static int handle_config(const char *key, const char *value,
-- struct key_value_info *kvi UNUSED, void *cb)
-+ struct key_value_info *kvi, void *cb)
- {
- const char *name;
- size_t namelen;
-@@ remote.c: 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);
-
- ## t/helper/test-config.c ##
-@@ t/helper/test-config.c: static int iterate_cb(const char *var, const char *value,
- 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(current_config_scope()));
-+ printf("scope=%s\n", config_scope_name(kvi->scope));
-
- return 0;
- }
## trace2.c ##
@@ trace2.c: void trace2_thread_exit_fl(const char *file, int line)
13: 11a32c86203 ! 11: 504eb206b5a config: pass kvi to die_bad_number()
@@ Commit message
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".
+ 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
@@ builtin/commit.c: static int git_commit_config(const char *k, const char *v,
## builtin/config.c ##
-@@ builtin/config.c: static int format_config(struct strbuf *buf, const char *key_, const char *value +@@ builtin/config.c: static int format_config(struct strbuf *buf, const char *key_,
if (type == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
@@ builtin/submodule--helper.c: static int update_clone_task_finished(int result,
## config.c ##
+@@ config.c: 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 +@@ config.c: 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;
+ }
+@@ config.c: 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;
+
@@ config.c: int git_parse_ssize_t(const char *value, ssize_t *ret)
return 1;
}
@@ config.c: int git_default_config(const char *var, const char *value,
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
+@@ config.c: static void configset_iter(struct config_reader *reader, struct config_set *set,
+ values = &entry->value_list;
+ kvi = values->items[value_index].util;
+
+- config_reader_set_kvi(reader, values->items[value_index].util);
+-
+ if (fn(entry->key, values->items[value_index].string, kvi, data) < 0)
+ git_die_config_linenr(entry->key, kvi->filename, kvi->linenr);
+- config_reader_set_kvi(reader, NULL);
+ }
+ }
+
@@ config.c: int git_configset_add_file(struct config_set *set, const char *filename)
return git_config_from_file(config_set_callback, filename, &data);
}
@@ config.c: int parse_config_key(const char *var,
-{
- 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;
@@ config.c: const char *config_scope_name(enum config_scope scope)
-{
- if (the_reader.config_kvi)
- *out = reader->config_kvi->filename;
+- else if (the_reader.source)
+- *out = reader->source->name;
- else
- return 1;
- return 0;
14: 33e59152293 ! 12: 52db0d3be82 config: remove config_reader from configset_add_value
@@ Metadata
Author: Glen Choo <[email protected]>
## Commit message ##
- config: remove config_reader from configset_add_value
+ config.c: remove config_reader from configsets
- Since we now get "kvi" from the config callback, we can stop passing it
- via "*data". Now "struct config_reader" has no more references, so get
- rid of it.
+ 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.
## config.c ##
-@@ config.c: struct config_source {
- };
- #define CONFIG_SOURCE_INIT { 0 }
-
--struct config_reader {
-- struct key_value_info *config_kvi;
--};
--/*
-- * 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_kvi(struct config_reader *reader,
-- struct key_value_info *kvi)
--{
-- kvi->prev = reader->config_kvi;
-- reader->config_kvi = kvi;
--}
--
--static inline struct key_value_info *config_reader_pop_kvi(struct config_reader *reader) --{
-- struct key_value_info *ret;
-- if (!reader->config_kvi)
-- BUG("tried to pop config_kvi, but we weren't reading config");
-- ret = reader->config_kvi;
-- reader->config_kvi = reader->config_kvi->prev;
-- return ret;
--}
--
- static int pack_compression_seen;
- static int zlib_compression_seen;
-
-@@ config.c: static int include_condition_is_true(struct key_value_info *kvi,
- return 0;
- }
-
--static int kvi_fn(config_fn_t fn, const char *key, const char *value,
-- struct key_value_info *kvi, void *data);
- static int git_config_include(const char *var, const char *value,
- struct key_value_info *kvi, void *data)
- {
-@@ config.c: 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 = kvi_fn(inc->fn, var, value, kvi, inc->data);
-+ ret = inc->fn(var, value, kvi, inc->data);
- if (ret < 0)
- return ret;
-
-@@ config.c: out_free_ret_1:
- return -CONFIG_INVALID_KEY;
- }
-
--static int kvi_fn(config_fn_t fn, const char *key, const char *value,
-- struct key_value_info *kvi, void *data)
--{
-- int ret;
-- config_reader_push_kvi(&the_reader, kvi);
-- ret = fn(key, value, kvi, data);
-- config_reader_pop_kvi(&the_reader);
-- return ret;
--}
--
- static int config_parse_pair(const char *key, const char *value,
- struct key_value_info *kvi,
- config_fn_t fn, void *data)
-@@ config.c: static int config_parse_pair(const char *key, const char *value,
- if (git_config_parse_key(key, &canonical_name, NULL))
- return -1;
-
-- ret = (kvi_fn(fn, canonical_name, value, kvi, data) < 0) ? -1 : 0;
-+ ret = (fn(canonical_name, value, kvi, data) < 0) ? -1 : 0;
- free(canonical_name);
+@@ config.c: int config_with_options(config_fn_t fn, void *data,
return ret;
}
-@@ config.c: static int get_value(struct config_source *cs, struct key_value_info *kvi,
- */
- cs->linenr--;
- kvi->linenr = cs->linenr;
-- ret = kvi_fn(fn, name->buf, value, kvi, data);
-+ ret = fn(name->buf, value, kvi, data);
- if (ret >= 0)
- cs->linenr++;
- return ret;
-@@ config.c: static void configset_iter(struct config_set *set, config_fn_t fn, void *data)
- values = &entry->value_list;
- kvi = values->items[value_index].util;
-- if (kvi_fn(fn, entry->key, values->items[value_index].string,
-- kvi, data) < 0)
-+ if (fn(entry->key, values->items[value_index].string, kvi,
-+ data) < 0)
- git_die_config_linenr(entry->key, kvi->filename,
- kvi->linenr);
- }
+-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;
@@ config.c: static int configset_find_element(struct config_set *set, const char *key,
- return 0;
}
--static int configset_add_value(struct config_reader *reader,
-- struct config_set *set, const char *key,
-- const char *value)
-+static int configset_add_value(struct config_set *set, const char *key,
-+ const char *value, struct key_value_info *kvi_p)
+ static int configset_add_value(struct key_value_info *kvi_p,
+- struct config_reader *reader,
+ struct config_set *set, const char *key,
+ const char *value)
{
- struct config_set_element *e;
- struct string_list_item *si;
-@@ config.c: static int configset_add_value(struct config_reader *reader, +@@ config.c: static int configset_add_value(struct key_value_info *kvi_p,
l_item->e = e;
l_item->value_index = e->value_list.nr - 1;
-- memcpy(kv_info, reader->config_kvi, sizeof(struct key_value_info));
+- if (reader->source->name) {
+- kvi_from_source(reader->source, kvi_p->scope, kv_info);
+- } else {
+- kvi_from_param(kv_info);
+- }
+ memcpy(kv_info, kvi_p, sizeof(struct key_value_info));
si->util = kv_info;
@@ config.c: void git_configset_clear(struct config_set *set)
- struct config_set *config_set;
- struct config_reader *config_reader;
-};
- #define CONFIGSET_ADD_INIT { 0 }
-
+-#define CONFIGSET_ADD_INIT { 0 }
+-
static int config_set_callback(const char *key, const char *value,
-- struct key_value_info *kvi UNUSED, void *cb)
-+ struct key_value_info *kvi, void *cb)
+ struct key_value_info *kvi, void *cb)
{
- struct configset_add_data *data = cb;
-- configset_add_value(data->config_reader, data->config_set, key, value);
+- configset_add_value(kvi, data->config_reader, data->config_set, key, value);
+ struct config_set *set = cb;
-+ configset_add_value(set, key, value, kvi);
++ configset_add_value(kvi, set, key, value);
return 0;
}
@@ config.c: static void repo_read_config(struct repository *repo)
git_configset_init(repo->config);
- data.config_set = repo->config;
- data.config_reader = &the_reader;
-
+-
- if (config_with_options(config_set_callback, &data, NULL, &opts) < 0)
-+ if (config_with_options(config_set_callback, repo->config, NULL, &opts) < 0)
++ if (config_with_options(config_set_callback, repo->config, NULL,
++ &opts) < 0)
/*
* config_with_options() normally returns only
* zero, as most errors are fatal, and
+@@ config.c: 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) @@ config.c: static void read_protected_config(void) .ignore_worktree = 1,
.system_gently = 1,
@@ config.c: static void read_protected_config(void)
}
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' */
4: b407fe1ed1d ! 13: 7d9b9eefc78 config: add kvi.path, use it to evaluate includes
@@ Commit message
Signed-off-by: Glen Choo <[email protected]>
## config.c ##
+@@ config.c: struct config_include_data {
+ void *data;
+ const struct config_options *opts;
+ struct git_config_source *config_source;
+- struct config_reader *config_reader;
+
+ /*
+ * All remote URLs discovered when reading all config files.
@@ config.c: 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,
+- struct key_value_info *kvi,
+- const char *path,
+static int handle_path_include(struct key_value_info *kvi, const char *path,
struct config_include_data *inc)
{
int ret = 0;
-@@ config.c: static int handle_path_include(struct config_source *cs, const char *path,
+@@ config.c: static int handle_path_include(struct config_source *cs,
if (!is_absolute_path(path)) {
char *slash;
@@ config.c: static int handle_path_include(struct config_source *cs, const char *p
strbuf_addstr(&buf, path);
path = buf.buf;
}
-@@ config.c: static int handle_path_include(struct config_source *cs, const char *path,
+@@ config.c: 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,
@@ config.c: static int handle_path_include(struct config_source *cs, const char *p
+ kvi->filename ? kvi->filename :
"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:
+ kvi->scope, NULL);
@@ config.c: static void add_trailing_starstar_for_dir(struct strbuf *pat)
strbuf_addstr(pat, "**");
}
@@ config.c: static int include_by_remote_url(struct config_include_data *inc,
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,
-@@ config.c: static int kvi_fn(config_fn_t fn, const char *key, const char *value,
- static int git_config_include(const char *var, const char *value, void *data)
+@@ config.c: static int git_config_include(const char *var, const char *value,
+ struct key_value_info *kvi, void *data)
{
struct config_include_data *inc = data;
- struct config_source *cs = inc->config_reader->source;
- struct key_value_info *kvi = inc->config_reader->config_kvi;
const char *cond, *key;
size_t cond_len;
-@@ config.c: static int git_config_include(const char *var, const char *value, void *data)
+ int ret;
+@@ config.c: 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, kvi, value, inc);
+ ret = handle_path_include(kvi, value, inc);
if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
@@ config.c: static int git_config_include(const char *var, const char *value, void
if (inc->opts->unconditional_remote_url)
inc->fn = forbid_remote_url;
-- ret = handle_path_include(cs, value, inc);
+- ret = handle_path_include(cs, kvi, value, inc);
+ ret = handle_path_include(kvi, value, inc);
inc->fn = old_fn;
}
-@@ config.c: static void kvi_from_param(struct key_value_info *out)
+@@ config.c: void kvi_from_param(struct key_value_info *out)
out->linenr = -1;
out->origin_type = CONFIG_ORIGIN_CMDLINE;
out->scope = CONFIG_SCOPE_COMMAND;
@@ config.c: static void kvi_from_source(struct config_source *cs,
}
static int git_parse_source(struct config_source *cs, config_fn_t fn,
+@@ config.c: int config_with_options(config_fn_t fn, void *data,
+ inc.data = data;
+ inc.opts = opts;
+ inc.config_source = config_source;
+- inc.config_reader = &the_reader;
+ fn = git_config_include;
+ data = &inc;
+ }
## config.h ##
@@ config.h: struct key_value_info {
@@ config.h: struct key_value_info {
enum config_origin_type origin_type;
enum config_scope scope;
+ const char *path;
- struct key_value_info *prev;
};
+ /** 5: e80d1b5f483 ! 14: 9e35b5b1f4d config: pass source to config_parser_event_fn_t
@@ Commit message
config.c, but this refactor is okay because this function has only ever been (and probably ever will be) used internally by config.c.
- This removes the last user of "config_reader.source", so remove it too.
+ 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.
## config.c ##
@@ config.c: struct config_source {
+ };
#define CONFIG_SOURCE_INIT { 0 }
- struct config_reader {
+-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).
-- *
-- * 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;
- };
- /*
-@@ config.c: struct config_reader {
- */
- static struct config_reader the_reader;
-
+-};
+-/*
+- * 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)
-{
@@ config.c: struct config_reader {
- return ret;
-}
-
- static inline void config_reader_push_kvi(struct config_reader *reader,
- struct key_value_info *kvi)
- {
+ static int pack_compression_seen;
+ static int zlib_compression_seen;
+
+@@ config.c: 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 = { 0 };
+
+- 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;
+@@ config.c: out:
+ strbuf_release(&envvar);
+ strvec_clear(&to_free);
+ free(envw);
+- config_reader_pop_source(&the_reader);
+ return ret;
+ }
+
@@ config.c: static int do_event(struct config_source *cs, enum config_event_t type,
if (data->previous_type != CONFIG_EVENT_EOF &&
@@ config.c: static int do_event(struct config_source *cs, enum config_event_t type
return -1;
data->previous_type = type;
-@@ config.c: int git_default_config(const char *var, const char *value, void *cb) +@@ config.c: int git_default_config(const char *var, const char *value,
* fgetc, ungetc, ftell of top need to be initialized before calling
* this function.
*/
@@ config.c: static int do_config_from_file(struct config_reader *reader,
- ret = do_config_from(reader, &top, fn, data, scope, opts);
+ ret = do_config_from(&top, fn, data, scope, opts);
funlockfile(f);
-
return ret;
+ }
@@ config.c: 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)
@@ config.c: int git_config_from_mem(config_fn_t fn,
}
int git_config_from_blob_oid(config_fn_t fn,
+@@ config.c: 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,
+ config_fn_t fn, void *data)
+ {
+ int ret = 0;
+@@ config.c: 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, fn, data);
++ ret = do_git_config_sequence(opts, fn, data);
+ }
+
+ if (inc.remote_urls) {
@@ config.c: void git_die_config(const char *key, const char *err, ...)
*/
@@ config.c: int git_config_set_multivar_in_file_gently(const char *config_filename
/* parse-key returns negative; flip the sign to feed exit(3) */
ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
if (ret)
-@@ config.c: static int reader_origin_type(struct config_reader *reader,
- {
- 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;
-@@ config.c: 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;
-@@ config.c: int current_config_line(void)
- if (the_reader.config_kvi)
- return the_reader.config_kvi->linenr;
- else
-- return the_reader.source->linenr;
-+ BUG("current_config_line called outside config callback");
- }
-
- int lookup_config(const char **mapping, int nr_mapping, const char *var)
## config.h ##
@@ config.h: enum config_event_t {
Signature · 1 line
gitgitgadget
PATCH v2 6/14 config.c: pass kvi in configsets
From: Glen Choo <[email protected]>
Trivially pass "struct key_value_info" to config callbacks in configset_iter(). Then, in config callbacks that are only used with configsets, use the "kvi" arg 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_*().
--- builtin/remote.c | 8 ++++---- config.c | 34 +++++++++++++++------------------- config.h | 2 +- remote.c | 6 +++--- t/helper/test-config.c | 10 +++++----- 5 files changed, 28 insertions(+), 32 deletions(-)
builtin/remote.c +4 -4
@@ -646,17 +646,17 @@ struct push_default_info };static int config_read_push_default (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {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 ; }
config.c +15 -19
@@ -2301,19 +2301,18 @@ 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 key_value_info *kvi;for (i =0 ; i < list->nr; i++) { entry = list->items[i].e; value_index = list->items[i].value_index; values = &entry->value_list; + kvi = values->items[value_index].util;config_reader_set_kvi (reader, values->items[value_index].util); -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); - +if (fn (entry->key, values->items[value_index].string, kvi, data) <0 ) +git_die_config_linenr (entry->key, kvi->filename, kvi->linenr);config_reader_set_kvi (reader,NULL ); } }
@@ -3951,13 +3950,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" ;
@@ -3974,6 +3968,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) {
@@ -4021,14 +4025,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;
config.h +1 -1
@@ -367,7 +367,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:
remote.c +3 -3
@@ -349,7 +349,7 @@ static void read_branches_file(struct remote_state *remote_state, }static int handle_config (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {const char *name;size_t namelen;
@@ -414,8 +414,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);
t/helper/test-config.c +5 -5
@@ -43,7 +43,7 @@*/ static int iterate_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data UNUSED) + struct key_value_info *kvi, void *data UNUSED) {static int nr;
@@ -52,10 +52,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 ; }
Signature · 1 line
gitgitgadget
PATCH v2 5/14 (RFC-only) config: finish config_fn_t refactor
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Here's an exhaustive list of all of the changes:
* Cases that need a judgement call
- trace2/tr2_cfg.c:tr2_cfg_set_fl()
This function needs to account for tr2_cfg_cb() now using "kvi". Since this is only called (indirectly) by git_config_set(), config source information has never been available here, so just pass NULL. It will be tr2_cfg_cb()'s responsibility to not use "kvi".
- builtin/checkout.c:checkout_main()
This calls git_xmerge_config() as a shorthand for parsing a CLI arg. "kvi" doesn't apply, so just pass NULL. This might be worth refactoring away, since git_xmerge_config() can call git_default_config().
* Hard for cocci to catch
- urlmatch.c
Manually refactor the custom config callbacks in "struct urlmatch_config".
- diff.h, fsck.h, grep.h, ident.h, xdiff-interface.h
"struct key_value_info" hasn't been defined yet, so forward declare it. Alternatively, maybe these files should "#include config.h".
* Likely deficiencies in .cocci patch
- submodule-config.c:gitmodules_cb()
Manually refactor a parse_config() call that gets missed because it uses a different "*data" arg.
- grep.h, various
Manually refactor grep_config() calls. Not sure why these don't get picked up.
- config.c:git_config_include(), http.c:http_options()
Manually add "kvi" where it was missed. Not sure why they get missed.
- builtin/clone.c:write_one_config()
Manually refactor a git_clone_config() call. Probably got missed because I didn't include git_config_parse_parameter().
- ident.h
Remove the UNUSED attribute. Not sure why this is the only instance of this.
- git-compat-util.h, compat/mingw.[h|c]
Manually refactor noop_core_config(), platform_core_config() and mingw_core_config(). I can probably add these as "manual fixups" in cocci.
--- builtin/checkout.c | 2 +- builtin/clone.c | 4 ++-- builtin/grep.c | 2 +- compat/mingw.c | 3 ++- compat/mingw.h | 4 +++- diff.h | 1 + fsck.h | 1 + git-compat-util.h | 2 ++ grep.c | 6 +++--- grep.h | 4 +++- http.c | 5 +++-- ident.h | 3 ++- submodule-config.c | 4 ++-- trace2/tr2_cfg.c | 2 +- urlmatch.c | 6 +++--- xdiff-interface.h | 2 ++ 16 files changed, 32 insertions(+), 19 deletions(-)
builtin/checkout.c +1 -1
@@ -1687,7 +1687,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,if (opts->conflict_style) { opts->merge =1 ;/* implied */ -git_xmerge_config ("merge.conflictstyle" , opts->conflict_style,NULL ); +git_xmerge_config ("merge.conflictstyle" , opts->conflict_style,NULL ,NULL ); }if (opts->force) { opts->discard_changes =1 ;
builtin/clone.c +2 -2
@@ -791,14 +791,14 @@ static int git_clone_config(const char *k, const char *v, }static int write_one_config (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {/* * give git_clone_config a chance to write config values back to the * environment, since git_config_set_multivar_gently only deals with * config-file writes */ -int apply_failed =git_clone_config (key, value, data); +int apply_failed =git_clone_config (key, value, kvi, data);if (apply_failed)return apply_failed;
builtin/grep.c +1 -1
@@ -290,7 +290,7 @@ static int wait_all(void)static int grep_cmd_config (const char *var,const char *value,struct key_value_info *kvi,void *cb) { -int st =grep_config (var, value, cb); +int st =grep_config (var, value, kvi, cb);if (git_color_config (var, value, cb) <0 ) st =-1 ;
compat/mingw.c +2 -1
@@ -242,7 +242,8 @@ static int core_restrict_inherited_handles = -1;static enum hide_dotfiles_type hide_dotfiles =HIDE_DOTFILES_DOTGITONLY ;static char *unset_environment_variables; -int mingw_core_config (const char *var,const char *value,void *cb) +int mingw_core_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {if (!strcmp (var,"core.hidedotfiles" )) {if (value && !strcasecmp (value,"dotgitonly" ))
compat/mingw.h +3 -1
@@ -11,7 +11,9 @@ typedef _sigset_t sigset_t;#undef _POSIX_THREAD_SAFE_FUNCTIONS#endif -int mingw_core_config (const char *var,const char *value,void *cb); +struct key_value_info ; +int mingw_core_config (const char *var,const char *value, +struct key_value_info *,void *cb);#define platform_core_config mingw_core_config/*
diff.h +1 -0
@@ -532,6 +532,7 @@ void free_diffstat_info(struct diffstat_t *diffstat);int parse_long_opt (const char *opt,const char **argv,const char **optarg); +struct key_value_info ;int git_diff_basic_config (const char *var,const char *value,struct key_value_info *kvi,void *cb);int git_diff_heuristic_config (const char *var,const char *value,void *cb);
fsck.h +1 -0
@@ -233,6 +233,7 @@ void fsck_put_object_name(struct fsck_options *options,const char *fsck_describe_object (struct fsck_options *options,const struct object_id *oid); +struct key_value_info ;/* * git_config() callback for use by fsck-y tools that want to support * fsck.<msg> fsck.skipList etc.
git-compat-util.h +2 -0
@@ -440,8 +440,10 @@ typedef uintmax_t timestamp_t;#endif #ifndef platform_core_config +struct key_value_info ; static inline int noop_core_config(const char *var UNUSED, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {return 0 ;
grep.c +3 -3
@@ -55,7 +55,7 @@ define_list_config_array_extra(color_grep_slots, {"match"});* the grep_defaults template. */ int grep_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct grep_opt *opt = cb;const char *slot;
@@ -90,9 +90,9 @@ int grep_config(const char *var, const char *value,if (!strcmp (var,"color.grep" )) opt->color =git_config_colorbool (var, value);if (!strcmp (var,"color.grep.match" )) { -if (grep_config ("color.grep.matchcontext" , value, cb) <0 ) +if (grep_config ("color.grep.matchcontext" , value, kvi, cb) <0 )return -1 ; -if (grep_config ("color.grep.matchselected" , value, cb) <0 ) +if (grep_config ("color.grep.matchselected" , value, kvi, cb) <0 )return -1 ; }else if (skip_prefix (var,"color.grep." , &slot)) {int i =LOOKUP_CONFIG (color_grep_slots, slot);
grep.h +3 -1
@@ -202,7 +202,9 @@ struct grep_opt { .output = std_output, \ } -int grep_config (const char *var,const char *value,void *); +struct key_value_info ; +int grep_config (const char *var,const char *value,struct key_value_info *kvi, +void *);void grep_init (struct grep_opt *,struct repository *repo);void append_grep_pat (struct grep_opt *opt,const char *pat,size_t patlen,const char *origin,int no,enum grep_pat_token t);
http.c +3 -2
@@ -361,7 +361,8 @@ static void process_curl_messages(void) } } -static int http_options (const char *var,const char *value,void *cb) +static int http_options (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp ("http.version" , var)) {return git_config_string (&curl_http_version, var, value);
@@ -532,7 +533,7 @@ static int http_options(const char *var, const char *value, void *cb) }/* Fall back on the default ones */ -return git_default_config (var, value, cb); +return git_default_config (var, value, kvi, cb); }static int curl_empty_auth_enabled (void )
ident.h +2 -1
@@ -62,7 +62,8 @@ const char *fmt_name(enum want_ident);int committer_ident_sufficiently_given (void );int author_ident_sufficiently_given (void ); +struct key_value_info ;int git_ident_config (const char *,const char *, -struct key_value_info *UNUSED ,void *); +struct key_value_info *,void *);#endif
submodule-config.c +2 -2
@@ -675,7 +675,7 @@ out: }static int gitmodules_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {struct repository *repo = data;struct parse_config_parameter parameter;
@@ -685,7 +685,7 @@ static int gitmodules_cb(const char *var, const char *value, parameter.gitmodules_oid =null_oid (); parameter.overwrite =1 ; -return parse_config (var, value, ¶meter); +return parse_config (var, value, kvi, ¶meter); }void repo_read_gitmodules (struct repository *repo,int skip_if_read)
trace2/tr2_cfg.c +1 -1
@@ -146,5 +146,5 @@ void tr2_cfg_set_fl(const char *file, int line, const char *key,struct tr2_cfg_data data = { file, line };if (tr2_cfg_load_patterns () >0 ) -tr2_cfg_cb (key, value, &data); +tr2_cfg_cb (key, value,NULL , &data); }
urlmatch.c +3 -3
@@ -552,7 +552,7 @@ static int cmp_matches(const struct urlmatch_item *a, }int urlmatch_config_entry (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct string_list_item *item;struct urlmatch_config *collect = cb;
@@ -566,7 +566,7 @@ int urlmatch_config_entry(const char *var, const char *value,if (!skip_prefix (var, collect->section, &key) || *(key++) !='.' ) {if (collect->cascade_fn) -return collect->cascade_fn (var, value, cb); +return collect->cascade_fn (var, value, kvi, cb);return 0 ;/* not interested */ } dot =strrchr (key,'.' );
@@ -610,7 +610,7 @@ int urlmatch_config_entry(const char *var, const char *value,strbuf_addstr (&synthkey, collect->section);strbuf_addch (&synthkey,'.' );strbuf_addstr (&synthkey, key); - retval = collect->collect_fn (synthkey.buf, value, collect->cb); + retval = collect->collect_fn (synthkey.buf, value, kvi, collect->cb);strbuf_release (&synthkey);return retval;
xdiff-interface.h +2 -0
@@ -50,6 +50,8 @@ int buffer_is_binary(const char *ptr, unsigned long size);void xdiff_set_find_func (xdemitconf_t *xecfg,const char *line,int cflags);void xdiff_clear_find_func (xdemitconf_t *xecfg); + +struct key_value_info ;int git_xmerge_config (const char *var,const char *value,struct key_value_info *kvi,void *cb);extern int git_xmerge_style;
Signature · 1 line
gitgitgadget
PATCH v2 7/14 config: provide kvi with config files
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Refactor out the configset logic that caches "struct config_source" and "enum config_scope" as a "struct key_value_info", and use it to pass the "kvi" arg to config callbacks when parsing config files. Get the "enum config_scope" value by plumbing an additional arg through git_config_from_file_with_options() and the underlying machinery.
We do not exercise the "kvi" arg 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 "kvi" yet.
--- bundle-uri.c | 1 + config.c | 104 +++++++++++++++++++++++++++++---------------- config.h | 8 ++-- fsck.c | 3 +- submodule-config.c | 5 ++- 5 files changed, 79 insertions(+), 42 deletions(-)
bundle-uri.c +1 -0
@@ -254,6 +254,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 ) {
config.c +68 -36
280 lines not on this page · raw message
config.h +5 -3
@@ -150,16 +150,18 @@ int git_default_config(const char *, const char *, struct key_value_info *,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);
fsck.c +2 -1
@@ -1236,7 +1236,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" );
submodule-config.c +3 -2
@@ -604,7 +604,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);
@@ -713,7 +713,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);
Signature · 1 line
gitgitgadget
PATCH v2 4/14 (RFC-only) config: apply cocci to config_fn_t implementations
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Pass "struct key_value_info" to *most* functions that are invoked as "config_fn_t" callbacks by applying contrib/coccinelle/config_fn_kvi.pending.cocci. None of the functions actually use the "kvi" arg yet (besides propagating it to a function that now expects "kvi"), but this will be addressed in a later commit. When deciding whether or not to propagate "kvi" to an inner function, only propagate the "kvi" arg if the inner function is actually invoked elsewhere as a config callback; it does not matter whether the function happens have the same signature as config_fn_t.
This commit does not build and has several style issues (e.g. a lack of spacing around the "kvi" arg), but I've split this out for the RFC so that it's more obvious which changes are automatic vs manual. Post-RFC I will squash this with the rest of the refactor + cocci changes.
--- alias.c | 3 ++- archive-tar.c | 3 ++- archive-zip.c | 1 + builtin/add.c | 5 +++-- builtin/blame.c | 5 +++-- builtin/branch.c | 5 +++-- builtin/cat-file.c | 5 +++-- builtin/checkout.c | 5 +++-- builtin/clean.c | 5 +++-- builtin/clone.c | 8 +++++--- builtin/column.c | 3 ++- builtin/commit-graph.c | 1 + builtin/commit.c | 10 ++++++---- builtin/config.c | 10 +++++++--- builtin/difftool.c | 5 +++-- builtin/fetch.c | 8 +++++--- builtin/fsmonitor--daemon.c | 5 +++-- builtin/grep.c | 5 +++-- builtin/help.c | 5 +++-- builtin/index-pack.c | 5 +++-- builtin/log.c | 10 ++++++---- builtin/merge.c | 7 ++++--- builtin/multi-pack-index.c | 1 + builtin/pack-objects.c | 5 +++-- builtin/patch-id.c | 5 +++-- builtin/pull.c | 5 +++-- builtin/push.c | 5 +++-- builtin/read-tree.c | 5 +++-- builtin/rebase.c | 5 +++-- builtin/receive-pack.c | 5 +++-- builtin/reflog.c | 7 ++++--- builtin/remote.c | 6 ++++-- builtin/repack.c | 5 +++-- builtin/reset.c | 5 +++-- builtin/send-pack.c | 5 +++-- builtin/show-branch.c | 5 +++-- builtin/stash.c | 5 +++-- builtin/submodule--helper.c | 1 + builtin/tag.c | 5 +++-- builtin/var.c | 5 +++-- builtin/worktree.c | 5 +++-- bundle-uri.c | 8 ++++++-- config.c | 28 ++++++++++++++++++---------- config.h | 3 ++- connect.c | 4 ++-- convert.c | 4 +++- credential.c | 1 + delta-islands.c | 3 ++- diff.c | 10 ++++++---- diff.h | 6 ++++-- fetch-pack.c | 5 +++-- fmt-merge-msg.c | 5 +++-- fmt-merge-msg.h | 3 ++- fsck.c | 8 +++++--- fsck.h | 3 ++- gpg-interface.c | 6 ++++-- grep.c | 3 ++- help.c | 7 +++++-- ident.c | 3 ++- ident.h | 3 ++- imap-send.c | 5 +++-- ll-merge.c | 1 + ls-refs.c | 2 +- mailinfo.c | 5 +++-- notes-utils.c | 3 ++- notes.c | 3 ++- pager.c | 5 ++++- pretty.c | 1 + promisor-remote.c | 4 +++- remote.c | 3 ++- revision.c | 3 ++- scalar.c | 3 ++- sequencer.c | 8 +++++--- setup.c | 15 ++++++++++----- submodule-config.c | 15 +++++++++++---- t/helper/test-config.c | 9 ++++++--- t/helper/test-userdiff.c | 4 +++- trace2/tr2_cfg.c | 3 ++- trace2/tr2_sysenv.c | 3 ++- trailer.c | 2 ++ upload-pack.c | 8 ++++++-- urlmatch.c | 3 ++- urlmatch.h | 3 ++- xdiff-interface.c | 5 +++-- xdiff-interface.h | 3 ++- 85 files changed, 285 insertions(+), 156 deletions(-)
alias.c +2 -1
@@ -11,7 +11,8 @@ struct config_alias_data {struct string_list *list; }; -static int config_alias_cb (const char *key,const char *value,void *d) +static int config_alias_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct config_alias_data *data = d;const char *p;
archive-tar.c +2 -1
@@ -410,7 +410,8 @@ static int tar_filter_config(const char *var, const char *value,return 0 ; } -static int git_tar_config (const char *var,const char *value,void *cb) +static int git_tar_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {if (!strcmp (var,"tar.umask" )) {if (value && !strcmp (value,"user" )) {
archive-zip.c +1 -0
@@ -616,6 +616,7 @@ static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time) }static int archive_zip_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {return userdiff_config (var, value);
builtin/add.c +3 -2
@@ -355,7 +355,8 @@ static struct option builtin_add_options[] = { OPT_END(), }; -static int add_config (const char *var,const char *value,void *cb) +static int add_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"add.ignoreerrors" ) || !strcmp (var,"add.ignore-errors" )) {
@@ -363,7 +364,7 @@ static int add_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } static const char embedded_advice[] = N_(
builtin/blame.c +3 -2
@@ -692,7 +692,8 @@ static const char *add_prefix(const char *prefix, const char *path)return prefix_path (prefix, prefix ?strlen (prefix) :0 , path); } -static int git_blame_config (const char *var,const char *value,void *cb) +static int git_blame_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"blame.showroot" )) { show_root =git_config_bool (var, value);
@@ -765,7 +766,7 @@ static int git_blame_config(const char *var, const char *value, void *cb)if (userdiff_config (var, value) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int blame_copy_callback (const struct option *option,const char *arg,int unset)
builtin/branch.c +3 -2
@@ -80,7 +80,8 @@ static unsigned int colopts;define_list_config_array (color_branch_slots); -static int git_branch_config (const char *var,const char *value,void *cb) +static int git_branch_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -117,7 +118,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static const char *branch_get_color (enum color_branch ix)
builtin/cat-file.c +3 -2
@@ -882,12 +882,13 @@ static int batch_objects(struct batch_options *opt)return retval; } -static int git_cat_file_config (const char *var,const char *value,void *cb) +static int git_cat_file_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (userdiff_config (var, value) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } static int batch_option_callback(const struct option *opt,
builtin/checkout.c +3 -2
@@ -1182,7 +1182,8 @@ static int switch_branches(const struct checkout_opts *opts,return ret || writeout_error; } -static int git_checkout_config (const char *var,const char *value,void *cb) +static int git_checkout_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct checkout_opts *opts = cb;
@@ -1198,7 +1199,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb)if (starts_with (var,"submodule." ))return git_default_submodule_config (var, value,NULL ); -return git_xmerge_config (var, value,NULL ); +return git_xmerge_config (var, value,kvi,NULL ); } static void setup_new_branch_info_and_source_tree(
builtin/clean.c +3 -2
@@ -102,7 +102,8 @@ struct menu_stuff {define_list_config_array (color_interactive_slots); -static int git_clean_config (const char *var,const char *value,void *cb) +static int git_clean_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -132,7 +133,7 @@ static int git_clean_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static const char *clean_get_color (enum color_clean ix)
builtin/clone.c +5 -3
@@ -775,7 +775,8 @@ static int checkout(int submodule_progress, int filter_submodules)return err; } -static int git_clone_config (const char *k,const char *v,void *cb) +static int git_clone_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"clone.defaultremotename" )) {free (remote_name);
@@ -786,10 +787,11 @@ static int git_clone_config(const char *k, const char *v, void *cb)if (!strcmp (k,"clone.filtersubmodules" )) config_filter_submodules =git_config_bool (k, v); -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); } -static int write_one_config (const char *key,const char *value,void *data) +static int write_one_config (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {/* * give git_clone_config a chance to write config values back to the
builtin/column.c +2 -1
@@ -13,7 +13,8 @@ static const char * const builtin_column_usage[] = { };static unsigned int colopts; -static int column_config (const char *var,const char *value,void *cb) +static int column_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {return git_column_config (var, value, cb, &colopts); }
builtin/commit-graph.c +1 -0
@@ -185,6 +185,7 @@ static int write_option_max_new_filters(const struct option *opt, }static int git_commit_graph_write_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var,"commitgraph.maxnewfilters" ))
builtin/commit.c +6 -4
@@ -1402,7 +1402,8 @@ static int parse_status_slot(const char *slot)return LOOKUP_CONFIG (color_status_slots, slot); } -static int git_status_config (const char *k,const char *v,void *cb) +static int git_status_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct wt_status *s = cb;const char *slot_name;
@@ -1487,7 +1488,7 @@ static int git_status_config(const char *k, const char *v, void *cb) s->detect_rename =git_config_rename (k, v);return 0 ; } -return git_diff_ui_config (k, v,NULL ); +return git_diff_ui_config (k, v,kvi,NULL ); }int cmd_status (int argc,const char **argv,const char *prefix)
@@ -1602,7 +1603,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)return 0 ; } -static int git_commit_config (const char *k,const char *v,void *cb) +static int git_commit_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct wt_status *s = cb;
@@ -1624,7 +1626,7 @@ static int git_commit_config(const char *k, const char *v, void *cb)return 0 ; } -return git_status_config (k, v, s); +return git_status_config (k, v,kvi, s); }int cmd_commit (int argc,const char **argv,const char *prefix)
builtin/config.c +7 -3
@@ -214,7 +214,7 @@ static void show_config_scope(struct strbuf *buf) }static int show_all_config (const char *key_,const char *value_, - void *cb UNUSED) + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (show_origin || show_scope) {struct strbuf buf =STRBUF_INIT ;
@@ -298,7 +298,8 @@ static int format_config(struct strbuf *buf, const char *key_, const char *valuereturn 0 ; } -static int collect_config (const char *key_,const char *value_,void *cb) +static int collect_config (const char *key_,const char *value_, + struct key_value_info *kvi UNUSED, void *cb) {struct strbuf_list *values = cb;
@@ -466,6 +467,7 @@ static const char *get_colorbool_slot;static char parsed_color[COLOR_MAXLEN ];static int git_get_color_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var, get_color_slot)) {
@@ -498,6 +500,7 @@ static int get_colorbool_found;static int get_diff_color_found;static int get_color_ui_found;static int git_get_colorbool_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var, get_colorbool_slot))
@@ -555,7 +558,8 @@ struct urlmatch_current_candidate_value {struct strbuf value; }; -static int urlmatch_collect_fn (const char *var,const char *value,void *cb) +static int urlmatch_collect_fn (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct string_list *values = cb;struct string_list_item *item =string_list_insert (values, var);
builtin/difftool.c +3 -2
@@ -38,14 +38,15 @@ static const char *const builtin_difftool_usage[] = { NULL }; -static int difftool_config (const char *var,const char *value,void *cb) +static int difftool_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"difftool.trustexitcode" )) { trust_exit_code =git_config_bool (var, value);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int print_tool_help (void )
builtin/fetch.c +5 -3
@@ -100,7 +100,8 @@ static int fetch_write_commit_graph = -1;static int stdin_refspecs =0 ;static int negotiate_only; -static int git_fetch_config (const char *k,const char *v,void *cb) +static int git_fetch_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"fetch.prune" )) { fetch_prune_config =git_config_bool (k, v);
@@ -140,7 +141,7 @@ static int git_fetch_config(const char *k, const char *v, void *cb)return 0 ; } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }static int parse_refmap_arg (const struct option *opt,const char *arg,int unset)
@@ -1828,7 +1829,8 @@ struct remote_group_data {struct string_list *list; }; -static int get_remote_group (const char *key,const char *value,void *priv) +static int get_remote_group (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *priv) {struct remote_group_data *g = priv;
builtin/fsmonitor--daemon.c +3 -2
@@ -36,7 +36,8 @@ static int fsmonitor__start_timeout_sec = 60;#define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup"static int fsmonitor__announce_startup =0 ; -static int fsmonitor_config (const char *var,const char *value,void *cb) +static int fsmonitor_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,FSMONITOR__IPC_THREADS )) {int i =git_config_int (var, value);
@@ -66,7 +67,7 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
builtin/grep.c +3 -2
@@ -287,13 +287,14 @@ static int wait_all(void)return hit; } -static int grep_cmd_config (const char *var,const char *value,void *cb) +static int grep_cmd_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {int st =grep_config (var, value, cb);if (git_color_config (var, value, cb) <0 ) st =-1 ; -else if (git_default_config (var, value, cb) <0 ) +else if (git_default_config (var, value,kvi, cb) <0 ) st =-1 ;if (!strcmp (var,"grep.threads" )) {
builtin/help.c +3 -2
@@ -396,7 +396,8 @@ static int add_man_viewer_info(const char *var, const char *value)return 0 ; } -static int git_help_config (const char *var,const char *value,void *cb) +static int git_help_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"help.format" )) {if (!value)
@@ -419,7 +420,7 @@ static int git_help_config(const char *var, const char *value, void *cb)if (starts_with (var,"man." ))return add_man_viewer_info (var, value); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static struct cmdnames main_cmds, other_cmds;
builtin/index-pack.c +3 -2
@@ -1578,7 +1578,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name,strbuf_release (&pack_name); } -static int git_index_pack_config (const char *k,const char *v,void *cb) +static int git_index_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct pack_idx_option *opts = cb;
@@ -1605,7 +1606,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)else opts->flags &= ~WRITE_REV ; } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }static int cmp_uint32 (const void *a_,const void *b_)
builtin/log.c +6 -4
@@ -559,7 +559,8 @@ static int cmd_log_walk(struct rev_info *rev)return retval; } -static int git_log_config (const char *var,const char *value,void *cb) +static int git_log_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *slot_name;
@@ -608,7 +609,7 @@ static int git_log_config(const char *var, const char *value, void *cb)return 0 ; } -return git_diff_ui_config (var, value, cb); +return git_diff_ui_config (var, value,kvi, cb); }int cmd_whatchanged (int argc,const char **argv,const char *prefix)
@@ -974,7 +975,8 @@ static enum cover_from_description parse_cover_from_description(const char *arg)die (_ ("%s: invalid cover from description mode" ), arg); } -static int git_format_config (const char *var,const char *value,void *cb) +static int git_format_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"format.headers" )) {if (!value)
@@ -1103,7 +1105,7 @@ static int git_format_config(const char *var, const char *value, void *cb)if (!strcmp (var,"diff.noprefix" ))return 0 ; -return git_log_config (var, value, cb); +return git_log_config (var, value,kvi, cb); }static const char *output_directory =NULL ;
builtin/merge.c +4 -3
@@ -620,7 +620,8 @@ static void parse_branch_merge_options(char *bmo)free (argv); } -static int git_merge_config (const char *k,const char *v,void *cb) +static int git_merge_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {int status;const char *str;
@@ -665,10 +666,10 @@ static int git_merge_config(const char *k, const char *v, void *cb)return 0 ; } - status =fmt_merge_msg_config (k, v, cb); + status =fmt_merge_msg_config (k, v,kvi, cb);if (status)return status; -return git_diff_ui_config (k, v, cb); +return git_diff_ui_config (k, v,kvi, cb); } static int read_tree_trivial(struct object_id *common, struct object_id *head,
builtin/multi-pack-index.c +1 -0
@@ -82,6 +82,7 @@ static struct option *add_common_options(struct option *prev) }static int git_multi_pack_index_write_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {if (!strcmp (var,"pack.writebitmaphashcache" )) {
builtin/pack-objects.c +3 -2
@@ -3134,7 +3134,8 @@ static void prepare_pack(int window, int depth)free (delta_list); } -static int git_pack_config (const char *k,const char *v,void *cb) +static int git_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"pack.window" )) { window =git_config_int (k, v);
@@ -3226,7 +3227,7 @@ static int git_pack_config(const char *k, const char *v, void *cb) ex->uri =xstrdup (pack_end +1 );oidmap_put (&configured_exclusions, ex); } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }/* Counters for trace2 output when in --stdin-packs mode. */
builtin/patch-id.c +3 -2
@@ -196,7 +196,8 @@ struct patch_id_opts {int verbatim; }; -static int git_patch_id_config (const char *var,const char *value,void *cb) +static int git_patch_id_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct patch_id_opts *opts = cb;
@@ -209,7 +210,7 @@ static int git_patch_id_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_patch_id (int argc,const char **argv,const char *prefix)
builtin/pull.c +3 -2
@@ -359,7 +359,8 @@ static enum rebase_type config_get_rebase(int *rebase_unspecified)/** * Read config variables. */ -static int git_pull_config (const char *var,const char *value,void *cb) +static int git_pull_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"rebase.autostash" )) { config_autostash =git_config_bool (var, value);
@@ -372,7 +373,7 @@ static int git_pull_config(const char *var, const char *value, void *cb) check_trust_level =0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/**
builtin/push.c +3 -2
@@ -506,7 +506,8 @@ static void set_push_cert_flags(int *flags, int v) } -static int git_push_config (const char *k,const char *v,void *cb) +static int git_push_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {const char *slot_name;int *flags = cb;
@@ -573,7 +574,7 @@ static int git_push_config(const char *k, const char *v, void *cb)return 0 ; } -return git_default_config (k, v,NULL ); +return git_default_config (k, v,kvi,NULL ); }int cmd_push (int argc,const char **argv,const char *prefix)
builtin/read-tree.c +3 -2
@@ -100,12 +100,13 @@ static int debug_merge(const struct cache_entry * const *stages,return 0 ; } -static int git_read_tree_config (const char *var,const char *value,void *cb) +static int git_read_tree_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"submodule.recurse" ))return git_default_submodule_config (var, value, cb); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_read_tree (int argc,const char **argv,const char *cmd_prefix)
builtin/rebase.c +3 -2
@@ -791,7 +791,8 @@ static void parse_rebase_merges_value(struct rebase_options *options, const chardie (_ ("Unknown rebase-merges mode: %s" ), value); } -static int rebase_config (const char *var,const char *value,void *data) +static int rebase_config (const char *var,const char *value, +struct key_value_info *kvi,void *data) {struct rebase_options *opts = data;
@@ -850,7 +851,7 @@ static int rebase_config(const char *var, const char *value, void *data)return git_config_string (&opts->default_backend, var, value); } -return git_default_config (var, value, data); +return git_default_config (var, value,kvi, data); }static int checkout_up_to_date (struct rebase_options *options)
builtin/receive-pack.c +3 -2
@@ -135,7 +135,8 @@ static enum deny_action parse_deny_action(const char *var, const char *value)return DENY_IGNORE ; } -static int receive_pack_config (const char *var,const char *value,void *cb) +static int receive_pack_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {int status =parse_hide_refs_config (var, value,"receive" , &hidden_refs);
@@ -262,7 +263,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void show_ref (const char *path,const struct object_id *oid)
builtin/reflog.c +4 -3
@@ -108,7 +108,8 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)#define EXPIRE_TOTAL 01#define EXPIRE_UNREACH 02 -static int reflog_expire_config (const char *var,const char *value,void *cb) +static int reflog_expire_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *pattern, *key;size_t pattern_len;
@@ -117,7 +118,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)struct reflog_expire_cfg *ent;if (parse_config_key (var,"gc" , &pattern, &pattern_len, &key) <0 ) -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb);if (!strcmp (key,"reflogexpire" )) { slot =EXPIRE_TOTAL ;
@@ -128,7 +129,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)if (git_config_expiry_date (&expire, var, value))return -1 ; }else -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb);if (!pattern) {switch (slot) {
builtin/remote.c +4 -2
@@ -268,6 +268,7 @@ static const char *abbrev_ref(const char *name, const char *prefix)#define abbrev_branch (name) abbrev_ref((name), "refs/heads/")static int config_read_branches (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {const char *orig_key = key;
@@ -645,7 +646,7 @@ struct push_default_info };static int config_read_push_default (const char *key,const char *value, -void *cb) + struct key_value_info *kvi UNUSED, void *cb) {struct push_default_info * info = cb; if (strcmp(key, "remote.pushdefault") ||
@@ -1494,7 +1495,8 @@ static int prune(int argc, const char **argv, const char *prefix)return result; } -static int get_remote_default(const char *key, const char *value UNUSED, void *priv) +static int get_remote_default(const char *key, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *priv) {if (strcmp (key,"remotes.default" ) ==0 ) {int *found = priv;
builtin/repack.c +3 -2
@@ -58,7 +58,8 @@ struct pack_objects_args {int local; }; -static int repack_config (const char *var,const char *value,void *cb) +static int repack_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct pack_objects_args *cruft_po_args = cb;if (!strcmp (var,"repack.usedeltabaseoffset" )) {
@@ -90,7 +91,7 @@ static int repack_config(const char *var, const char *value, void *cb)return git_config_string (&cruft_po_args->depth, var, value);if (!strcmp (var,"repack.cruftthreads" ))return git_config_string (&cruft_po_args->threads, var, value); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
builtin/reset.c +3 -2
@@ -308,12 +308,13 @@ static int reset_refs(const char *rev, const struct object_id *oid)return update_ref_status; } -static int git_reset_config (const char *var,const char *value,void *cb) +static int git_reset_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"submodule.recurse" ))return git_default_submodule_config (var, value, cb); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }int cmd_reset (int argc,const char **argv,const char *prefix)
builtin/send-pack.c +3 -2
@@ -131,7 +131,8 @@ static void print_helper_status(struct ref *ref)strbuf_release (&buf); } -static int send_pack_config (const char *k,const char *v,void *cb) +static int send_pack_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {if (!strcmp (k,"push.gpgsign" )) {const char *value;
@@ -151,7 +152,7 @@ static int send_pack_config(const char *k, const char *v, void *cb) } } } -return git_default_config (k, v, cb); +return git_default_config (k, v,kvi, cb); }int cmd_send_pack (int argc,const char **argv,const char *prefix)
builtin/show-branch.c +3 -2
@@ -556,7 +556,8 @@ static void append_one_rev(const char *av)die ("bad sha1 reference %s" , av); } -static int git_show_branch_config (const char *var,const char *value,void *cb) +static int git_show_branch_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"showbranch.default" )) {if (!value)
@@ -579,7 +580,7 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int omit_in_dense (struct commit *commit,struct commit **rev,int n)
builtin/stash.c +3 -2
@@ -836,7 +836,8 @@ static int show_stat = 1;static int show_patch;static int show_include_untracked; -static int git_stash_config (const char *var,const char *value,void *cb) +static int git_stash_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"stash.showstat" )) { show_stat =git_config_bool (var, value);
@@ -850,7 +851,7 @@ static int git_stash_config(const char *var, const char *value, void *cb) show_include_untracked =git_config_bool (var, value);return 0 ; } -return git_diff_basic_config (var, value, cb); +return git_diff_basic_config (var, value,kvi, cb); }static void diff_include_untracked (const struct stash_info *info,struct diff_options *diff_opt)
builtin/submodule--helper.c +1 -0
@@ -2187,6 +2187,7 @@ static int update_clone_task_finished(int result, }static int git_update_clone_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *cb) {int *max_jobs = cb;
builtin/tag.c +3 -2
@@ -183,7 +183,8 @@ static const char tag_template_nocleanup[] ="Lines starting with '%c' will be kept; you may remove them" " yourself if you want to.\n"); -static int git_tag_config (const char *var,const char *value,void *cb) +static int git_tag_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"tag.gpgsign" )) { config_sign_tag =git_config_bool (var, value);
@@ -208,7 +209,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void write_tag_body (int fd,const struct object_id *oid)
builtin/var.c +3 -2
@@ -69,13 +69,14 @@ static const struct git_var *get_git_var(const char *var)return NULL ; } -static int show_config (const char *var,const char *value,void *cb) +static int show_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (value)printf ("%s=%s\n" , var, value);else printf ("%s\n" , var); -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); } int cmd_var(int argc, const char **argv, const char *prefix UNUSED)
builtin/worktree.c +3 -2
@@ -103,14 +103,15 @@ static int verbose;static int guess_remote;static timestamp_t expire; -static int git_worktree_config (const char *var,const char *value,void *cb) +static int git_worktree_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"worktree.guessremote" )) { guess_remote =git_config_bool (var, value);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int delete_git_dir (const char *id)
bundle-uri.c +6 -2
@@ -223,7 +223,9 @@ static int bundle_list_update(const char *key, const char *value,return 0 ; } -static int config_to_bundle_list (const char *key,const char *value,void *data) +static int config_to_bundle_list (const char *key,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct bundle_list *list = data;return bundle_list_update (key, value, list);
@@ -870,7 +872,9 @@ cached:return advertise_bundle_uri; } -static int config_to_packet_line (const char *key,const char *value,void *data) +static int config_to_packet_line (const char *key,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct packet_reader *writer = data;
config.c +18 -10
@@ -201,7 +201,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, +struct key_value_info *kvi,void *data);#define MAX_INCLUDE_DEPTH 10 static const char include_depth_advice[] = N_(
@@ -380,7 +381,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, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *remote_urls = data;const char *remote_name;
@@ -414,6 +416,7 @@ static void populate_remote_urls(struct config_include_data *inc) } static int forbid_remote_url(const char *var, const char *value UNUSED, + struct key_value_info *kvi UNUSED, void *data UNUSED) {const char *remote_name;
@@ -477,7 +480,8 @@ 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, + struct key_value_info *kvi UNUSED, void *data) {struct config_include_data *inc = data;struct config_source *cs = inc->config_reader->source;
@@ -1553,7 +1557,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, +struct key_value_info *kvi,void *cb) {/* This needs a better name */ if (!strcmp (var,"core.filemode" )) {
@@ -1838,7 +1843,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,kvi, cb); }static int git_default_sparse_config (const char *var,const char *value)
@@ -1940,15 +1945,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, +struct key_value_info *kvi,void *cb) {if (starts_with (var,"core." )) -return git_default_core_config (var, value, cb); +return git_default_core_config (var, value,kvi, 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,kvi, cb);if (starts_with (var,"i18n." ))return git_default_i18n_config (var, value);
@@ -2481,7 +2487,8 @@ 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, + struct key_value_info *kvi UNUSED, void *cb) {struct configset_add_data *data = cb;configset_add_value (data->config_reader, data->config_set, key, value);
@@ -3091,7 +3098,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, + struct key_value_info *kvi UNUSED, void *cb) {struct config_store_data *store = cb;
config.h +2 -1
@@ -138,7 +138,8 @@ struct key_value_info {*/ typedef int (*config_fn_t )(const char *,const char *,struct key_value_info *,void *); -int git_default_config (const char *,const char *,void *); +int git_default_config (const char *,const char *,struct key_value_info *, +void *);/** * Read a specific file in git-config format.
connect.c +2 -2
@@ -962,7 +962,7 @@ static struct child_process *git_tcp_connect(int fd[2], char *host, int flags)static char *git_proxy_command;static int git_proxy_command_options (const char *var,const char *value, -void *cb) +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"core.gitproxy" )) {const char *for_pos;
@@ -1008,7 +1008,7 @@ static int git_proxy_command_options(const char *var, const char *value,return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static int git_use_proxy (const char *host)
convert.c +3 -1
@@ -1011,7 +1011,9 @@ static int apply_filter(const char *path, const char *src, size_t len,return 0 ; } -static int read_convert_config(const char *var, const char *value, void *cb UNUSED) +static int read_convert_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, + void *cb UNUSED) {const char *key, *name;size_t namelen;
credential.c +1 -0
@@ -46,6 +46,7 @@ static int credential_from_potentially_partial_url(struct credential *c, const char *url);static int credential_config_callback (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *data) {struct credential *c = data;
delta-islands.c +2 -1
@@ -341,7 +341,8 @@ static void free_remote_islands(kh_str_t *remote_islands)kh_destroy_str (remote_islands); } -static int island_config_callback (const char *k,const char *v,void *cb) +static int island_config_callback (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {struct island_load_data *ild = cb;
diff.c +6 -4
@@ -350,7 +350,8 @@ static unsigned parse_color_moved_ws(const char *arg)return ret; } -int git_diff_ui_config (const char *var,const char *value,void *cb) +int git_diff_ui_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"diff.color" ) || !strcmp (var,"color.diff" )) { diff_use_color_default =git_config_colorbool (var, value);
@@ -433,10 +434,11 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)if (git_color_config (var, value, cb) <0 )return -1 ; -return git_diff_basic_config (var, value, cb); +return git_diff_basic_config (var, value,kvi, cb); } -int git_diff_basic_config (const char *var,const char *value,void *cb) +int git_diff_basic_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {const char *name;
@@ -488,7 +490,7 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)if (git_diff_heuristic_config (var, value, cb) <0 )return -1 ; -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static char *quote_two (const char *one,const char *two)
diff.h +4 -2
@@ -532,10 +532,12 @@ void free_diffstat_info(struct diffstat_t *diffstat);int parse_long_opt (const char *opt,const char **argv,const char **optarg); -int git_diff_basic_config (const char *var,const char *value,void *cb); +int git_diff_basic_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);int git_diff_heuristic_config (const char *var,const char *value,void *cb);void init_diff_ui_defaults (void ); -int git_diff_ui_config (const char *var,const char *value,void *cb); +int git_diff_ui_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);void repo_diff_setup (struct repository *,struct diff_options *);struct option *add_diff_options (const struct option *,struct diff_options *);int diff_opt_parse (struct diff_options *,const char **,int ,const char *);
fetch-pack.c +3 -2
@@ -1858,7 +1858,8 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,return ref; } -static int fetch_pack_config_cb (const char *var,const char *value,void *cb) +static int fetch_pack_config_cb (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (strcmp (var,"fetch.fsck.skiplist" ) ==0 ) {const char *path;
@@ -1880,7 +1881,7 @@ static int fetch_pack_config_cb(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }static void fetch_pack_config (void )
fmt-merge-msg.c +3 -2
@@ -19,7 +19,8 @@ static int use_branch_desc;static int suppress_dest_pattern_seen;static struct string_list suppress_dest_patterns =STRING_LIST_INIT_DUP ; -int fmt_merge_msg_config (const char *key,const char *value,void *cb) +int fmt_merge_msg_config (const char *key,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (key,"merge.log" ) || !strcmp (key,"merge.summary" )) {int is_bool;
@@ -39,7 +40,7 @@ int fmt_merge_msg_config(const char *key, const char *value, void *cb)string_list_append (&suppress_dest_patterns, value); suppress_dest_pattern_seen =1 ; }else { -return git_default_config (key, value, cb); +return git_default_config (key, value,kvi, cb); }return 0 ; }
fmt-merge-msg.h +2 -1
@@ -13,7 +13,8 @@ struct fmt_merge_msg_opts { };extern int merge_log_config; -int fmt_merge_msg_config (const char *key,const char *value,void *cb); +int fmt_merge_msg_config (const char *key,const char *value, +struct key_value_info *kvi,void *cb);int fmt_merge_msg (struct strbuf *in,struct strbuf *out,struct fmt_merge_msg_opts *);
fsck.c +5 -3
@@ -1162,7 +1162,8 @@ struct fsck_gitmodules_data {int ret; }; -static int fsck_gitmodules_fn (const char *var,const char *value,void *vdata) +static int fsck_gitmodules_fn (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *vdata) {struct fsck_gitmodules_data *data = vdata;const char *subsection, *key;
@@ -1372,7 +1373,8 @@ int fsck_finish(struct fsck_options *options)return ret; } -int git_fsck_config (const char *var,const char *value,void *cb) +int git_fsck_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {struct fsck_options *options = cb;if (strcmp (var,"fsck.skiplist" ) ==0 ) {
@@ -1393,7 +1395,7 @@ int git_fsck_config(const char *var, const char *value, void *cb)return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }/*
fsck.h +2 -1
@@ -237,6 +237,7 @@ const char *fsck_describe_object(struct fsck_options *options,* git_config() callback for use by fsck-y tools that want to support * fsck.<msg> fsck.skipList etc. */ -int git_fsck_config (const char *var,const char *value,void *cb); +int git_fsck_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);#endif
gpg-interface.c +4 -2
@@ -12,7 +12,8 @@#include "alias.h" #include "wrapper.h" -static int git_gpg_config (const char *,const char *,void *); +static int git_gpg_config (const char *,const char *,struct key_value_info *, +void *);static void gpg_interface_lazy_init (void ) {
@@ -718,7 +719,8 @@ void set_signing_key(const char *key) configured_signing_key =xstrdup (key); } -static int git_gpg_config(const char *var, const char *value, void *cb UNUSED) +static int git_gpg_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct gpg_format *fmt =NULL ;char *fmtname =NULL ;
grep.c +2 -1
@@ -54,7 +54,8 @@ define_list_config_array_extra(color_grep_slots, {"match"});* Read the configuration file once and store it in * the grep_defaults template. */ -int grep_config (const char *var,const char *value,void *cb) +int grep_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct grep_opt *opt = cb;const char *slot;
help.c +5 -2
@@ -309,7 +309,8 @@ void load_command_list(const char *prefix,exclude_cmds (other_cmds, main_cmds); } -static int get_colopts (const char *var,const char *value,void *data) +static int get_colopts (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {unsigned int *colopts = data;
@@ -459,7 +460,8 @@ void list_developer_interfaces_help(void)putchar ('\n' ); } -static int get_alias (const char *var,const char *value,void *data) +static int get_alias (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *list = data;
@@ -543,6 +545,7 @@ static struct cmdnames aliases;#define AUTOCORRECT_IMMEDIATELY (-1)static int git_unknown_cmd_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *p;
ident.c +2 -1
@@ -671,7 +671,8 @@ static int set_ident(const char *var, const char *value)return 0 ; } -int git_ident_config(const char *var, const char *value, void *data UNUSED) +int git_ident_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var,"user.useconfigonly" )) { ident_use_config_only =git_config_bool (var, value);
ident.h +2 -1
@@ -62,6 +62,7 @@ const char *fmt_name(enum want_ident);int committer_ident_sufficiently_given (void );int author_ident_sufficiently_given (void ); -int git_ident_config (const char *,const char *,void *); +int git_ident_config (const char *,const char *, +struct key_value_info *UNUSED ,void *);#endif
imap-send.c +3 -2
@@ -1322,7 +1322,8 @@ static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)return 1 ; } -static int git_imap_config (const char *var,const char *val,void *cb) +static int git_imap_config (const char *var,const char *val, +struct key_value_info *kvi,void *cb) {if (!strcmp ("imap.sslverify" , var))
@@ -1356,7 +1357,7 @@ static int git_imap_config(const char *var, const char *val, void *cb) server.host =xstrdup (val); } }else -return git_default_config (var, val, cb); +return git_default_config (var, val,kvi, cb);return 0 ; }
ll-merge.c +1 -0
@@ -252,6 +252,7 @@ static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;static const char *default_ll_merge;static int read_merge_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct ll_merge_driver *fn;
ls-refs.c +1 -1
@@ -136,7 +136,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data) }static int ls_refs_config (const char *var,const char *value, -void *cb_data) + struct key_value_info *kvi UNUSED, void *cb_data) {struct ls_refs_data *data = cb_data;/*
mailinfo.c +3 -2
@@ -1241,12 +1241,13 @@ int mailinfo_parse_quoted_cr_action(const char *actionstr, int *action)return 0 ; } -static int git_mailinfo_config (const char *var,const char *value,void *mi_) +static int git_mailinfo_config (const char *var,const char *value, +struct key_value_info *kvi,void *mi_) {struct mailinfo *mi = mi_;if (!starts_with (var,"mailinfo." )) -return git_default_config (var, value,NULL ); +return git_default_config (var, value,kvi,NULL );if (!strcmp (var,"mailinfo.scissors" )) { mi->use_scissors =git_config_bool (var, value);return 0 ;
notes-utils.c +2 -1
@@ -93,7 +93,8 @@ static combine_notes_fn parse_combine_notes_fn(const char *v)return NULL ; } -static int notes_rewrite_config (const char *k,const char *v,void *cb) +static int notes_rewrite_config (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {struct notes_rewrite_cfg *c = cb;if (starts_with (k,"notes.rewrite." ) && !strcmp (k+14 , c->cmd)) {
notes.c +2 -1
@@ -973,7 +973,8 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,free (globs_copy); } -static int notes_display_config (const char *k,const char *v,void *cb) +static int notes_display_config (const char *k,const char *v, + struct key_value_info *kvi UNUSED, void *cb) {int *load_refs = cb;
pager.c +4 -1
@@ -39,6 +39,7 @@ static void wait_for_pager_signal(int signo) }static int core_pager_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {if (!strcmp (var,"core.pager" ))
@@ -224,7 +225,9 @@ struct pager_command_config_data {char *value; }; -static int pager_command_config (const char *var,const char *value,void *vdata) +static int pager_command_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *vdata) {struct pager_command_config_data *data = vdata;const char *cmd;
pretty.c +1 -0
@@ -55,6 +55,7 @@ static void save_user_format(struct rev_info *rev, const char *cp, int is_tforma }static int git_pretty_formats_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {struct cmt_fmt_map *commit_format =NULL ;
promisor-remote.c +3 -1
@@ -99,7 +99,9 @@ static void promisor_remote_move_to_tail(struct promisor_remote_config *config, config->promisors_tail = &r->next; } -static int promisor_remote_config (const char *var,const char *value,void *data) +static int promisor_remote_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *data) {struct promisor_remote_config *config = data;const char *name;
remote.c +2 -1
@@ -348,7 +348,8 @@ static void read_branches_file(struct remote_state *remote_state, remote->fetch_tags =1 ;/* always auto-follow */ } -static int handle_config (const char *key,const char *value,void *cb) +static int handle_config (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {const char *name;size_t namelen;
revision.c +2 -1
@@ -1569,7 +1569,8 @@ struct exclude_hidden_refs_cb {const char *section; }; -static int hide_refs_config (const char *var,const char *value,void *cb_data) +static int hide_refs_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb_data) {struct exclude_hidden_refs_cb *cb = cb_data; cb->exclusions->hidden_refs_configured =1 ;
scalar.c +2 -1
@@ -593,7 +593,8 @@ static int cmd_register(int argc, const char **argv)return register_dir (); } -static int get_scalar_repos (const char *key,const char *value,void *data) +static int get_scalar_repos (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct string_list *list = data;
sequencer.c +5 -3
@@ -214,7 +214,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref)return rec; } -static int git_sequencer_config (const char *k,const char *v,void *cb) +static int git_sequencer_config (const char *k,const char *v, +struct key_value_info *kvi,void *cb) {struct replay_opts *opts = cb;int status;
@@ -269,7 +270,7 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)if (opts->action ==REPLAY_REVERT && !strcmp (k,"revert.reference" )) opts->commit_use_reference =git_config_bool (k, v); -return git_diff_basic_config (k, v,NULL ); +return git_diff_basic_config (k, v,kvi,NULL ); }void sequencer_init_config (struct replay_opts *opts)
@@ -2876,7 +2877,8 @@ static int git_config_string_dup(char **dest,return 0 ; } -static int populate_opts_cb (const char *key,const char *value,void *data) +static int populate_opts_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct replay_opts *opts = data;int error_flag =1 ;
setup.c +10 -5
@@ -514,7 +514,9 @@ no_prevention_needed: startup_info->original_cwd =NULL ; } -static int read_worktree_config (const char *var,const char *value,void *vdata) +static int read_worktree_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *vdata) {struct repository_format *data = vdata;
@@ -585,7 +587,8 @@ static enum extension_result handle_extension(const char *var,return EXTENSION_UNKNOWN ; } -static int check_repo_format (const char *var,const char *value,void *vdata) +static int check_repo_format (const char *var,const char *value, +struct key_value_info *kvi,void *vdata) {struct repository_format *data = vdata;const char *ext;
@@ -614,7 +617,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata) } } -return read_worktree_config (var, value, vdata); +return read_worktree_config (var, value,kvi, vdata); }static int check_repository_format_gently (const char *gitdir,struct repository_format *candidate,int *nongit_ok)
@@ -1113,7 +1116,8 @@ struct safe_directory_data {int is_safe; }; -static int safe_directory_cb (const char *key,const char *value,void *d) +static int safe_directory_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct safe_directory_data *data = d;
@@ -1169,7 +1173,8 @@ static int ensure_valid_ownership(const char *gitfile,return data.is_safe; } -static int allowed_bare_repo_cb (const char *key,const char *value,void *d) +static int allowed_bare_repo_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {enum allowed_bare_repo *allowed_bare_repo = d;
submodule-config.c +11 -4
@@ -424,7 +424,8 @@ struct parse_config_parameter {* config store (.git/config, etc). Callers are responsible for * checking for overrides in the main config store when appropriate. */ -static int parse_config (const char *var,const char *value,void *data) +static int parse_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct parse_config_parameter *me = data;struct submodule *submodule;
@@ -673,7 +674,8 @@ out: } } -static int gitmodules_cb (const char *var,const char *value,void *data) +static int gitmodules_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {struct repository *repo = data;struct parse_config_parameter parameter;
@@ -800,7 +802,9 @@ void submodule_free(struct repository *r)submodule_cache_clear (r->submodule_cache); } -static int config_print_callback (const char *var,const char *value,void *cb_data) +static int config_print_callback (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {char *wanted_key = cb_data;
@@ -842,7 +846,9 @@ struct fetch_config {int *recurse_submodules; }; -static int gitmodules_fetch_config (const char *var,const char *value,void *cb) +static int gitmodules_fetch_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb) {struct fetch_config *config = cb;if (!strcmp (var,"submodule.fetchjobs" )) {
@@ -870,6 +876,7 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules) }static int gitmodules_update_clone_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED,void *cb) {int *max_jobs = cb;
t/helper/test-config.c +6 -3
@@ -42,7 +42,8 @@* */ -static int iterate_cb(const char *var, const char *value, void *data UNUSED) +static int iterate_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data UNUSED) {static int nr;
@@ -59,7 +60,8 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED)return 0 ; } -static int parse_int_cb (const char *var,const char *value,void *data) +static int parse_int_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *data) {const char *key_to_match = data;
@@ -70,7 +72,8 @@ static int parse_int_cb(const char *var, const char *value, void *data)return 0 ; } -static int early_config_cb (const char *var,const char *value,void *vdata) +static int early_config_cb (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *vdata) {const char *key = vdata;
t/helper/test-userdiff.c +3 -1
@@ -12,7 +12,9 @@ static int driver_cb(struct userdiff_driver *driver,return 0 ; } -static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED) +static int cmd__userdiff_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, + void *cb UNUSED) {if (userdiff_config (var, value) <0 )return -1 ;
trace2/tr2_cfg.c +2 -1
@@ -99,7 +99,8 @@ 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,void *d) +static int tr2_cfg_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {struct strbuf **s;struct tr2_cfg_data *data = (struct tr2_cfg_data *)d;
trace2/tr2_sysenv.c +2 -1
@@ -57,7 +57,8 @@ static struct tr2_sysenv_entry tr2_sysenv_settings[] = { };/* clang-format on */ -static int tr2_sysenv_cb (const char *key,const char *value,void *d) +static int tr2_sysenv_cb (const char *key,const char *value, + struct key_value_info *kvi UNUSED, void *d) {int k;
trailer.c +2 -0
@@ -482,6 +482,7 @@ static struct { };static int git_trailer_default_config (const char *conf_key,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *trailer_item, *variable_name;
@@ -514,6 +515,7 @@ static int git_trailer_default_config(const char *conf_key, const char *value, }static int git_trailer_config (const char *conf_key,const char *value, + struct key_value_info *kvi UNUSED, void *cb UNUSED) {const char *trailer_item, *variable_name;
upload-pack.c +6 -2
@@ -1298,7 +1298,9 @@ static int parse_object_filter_config(const char *var, const char *value,return 0 ; } -static int upload_pack_config (const char *var,const char *value,void *cb_data) +static int upload_pack_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {struct upload_pack_data *data = cb_data;
@@ -1339,7 +1341,9 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)return parse_hide_refs_config (var, value,"uploadpack" , &data->hidden_refs); } -static int upload_pack_protected_config (const char *var,const char *value,void *cb_data) +static int upload_pack_protected_config (const char *var,const char *value, + struct key_value_info *kvi UNUSED, +void *cb_data) {struct upload_pack_data *data = cb_data;
urlmatch.c +2 -1
@@ -551,7 +551,8 @@ static int cmp_matches(const struct urlmatch_item *a,return 0 ; } -int urlmatch_config_entry (const char *var,const char *value,void *cb) +int urlmatch_config_entry (const char *var,const char *value, + struct key_value_info *kvi UNUSED, void *cb) {struct string_list_item *item;struct urlmatch_config *collect = cb;
urlmatch.h +2 -1
@@ -71,7 +71,8 @@ struct urlmatch_config { .vars = STRING_LIST_INIT_DUP, \ } -int urlmatch_config_entry (const char *var,const char *value,void *cb); +int urlmatch_config_entry (const char *var,const char *value, +struct key_value_info *kvi,void *cb);void urlmatch_config_release (struct urlmatch_config *config);#endif /* URL_MATCH_H */
xdiff-interface.c +3 -2
@@ -307,7 +307,8 @@ int xdiff_compare_lines(const char *l1, long s1,int git_xmerge_style =-1 ; -int git_xmerge_config (const char *var,const char *value,void *cb) +int git_xmerge_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb) {if (!strcmp (var,"merge.conflictstyle" )) {if (!value)
@@ -327,5 +328,5 @@ int git_xmerge_config(const char *var, const char *value, void *cb) value, var);return 0 ; } -return git_default_config (var, value, cb); +return git_default_config (var, value,kvi, cb); }
xdiff-interface.h +2 -1
@@ -50,7 +50,8 @@ int buffer_is_binary(const char *ptr, unsigned long size);void xdiff_set_find_func (xdemitconf_t *xecfg,const char *line,int cflags);void xdiff_clear_find_func (xdemitconf_t *xecfg); -int git_xmerge_config (const char *var,const char *value,void *cb); +int git_xmerge_config (const char *var,const char *value, +struct key_value_info *kvi,void *cb);extern int git_xmerge_style;/*
Signature · 1 line
gitgitgadget
PATCH v2 9/14 config.c: provide kvi with CLI config
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
Refactor out kvi_from_param() from the logic that caches CLI config in configsets, and use it to pass the "kvi" arg to config callbacks when parsing CLI config. Now that "kvi" is always present when config machinery calls config callbacks, plumb "kvi" so that we can replace nearly all calls to current_config_*(). (The exception is an edge case where trace2/*.c calls current_config_scope(). That will be handled in a later commit.) 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.
* "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration. Fix this by copying the "kvi" arg 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" (we don't allow this combination of args because of this bug), but that is left unchanged for now.
* "git config --default" doesn't have config source metadata when displaying the default value. 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().
--- builtin/config.c | 41 ++++++++++++++----------- config.c | 78 ++++++++++++++++++++++------------------------- config.h | 3 +- t/t1300-config.sh | 10 +++--- 4 files changed, 68 insertions(+), 64 deletions(-)
builtin/config.c +24 -17
@@ -191,37 +191,37 @@ 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 (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 (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_, - struct key_value_info *kvi UNUSED, void *cb UNUSED) + struct key_value_info *kvi, void *cb UNUSED) {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);
@@ -239,12 +239,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_,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) {
@@ -299,7 +300,7 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value }static int collect_config (const char *key_,const char *value_, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct strbuf_list *values = cb;
@@ -316,7 +317,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)
@@ -377,11 +378,14 @@ static int get_value(const char *key_, const char *regex_, unsigned flags) &given_config_source, &config_options);if (!values.nr && default_value) { +struct key_value_info kvi = {0 };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); }
@@ -556,10 +560,11 @@ 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, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,void *cb) {struct string_list *values = cb;struct string_list_item *item =string_list_insert (values, var);
@@ -572,6 +577,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, }else {strbuf_reset (&matched->value); } +memcpy (&matched->kvi, kvi,sizeof (struct key_value_info ));if (value) {strbuf_addstr (&matched->value, value);
@@ -618,7 +624,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);
config.c +37 -41
196 lines not on this page · raw message
config.h +1 -2
@@ -367,9 +367,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:
t/t1300-config.sh +6 -4
@@ -1635,8 +1635,8 @@ test_expect_success 'urlmatch with --show-scope' ' EOF cat >expect <<-EOF && - unknown http.cookiefile /tmp/cookie.txt - unknown http.sslverify false + 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
@@ -2030,7 +2030,9 @@ test_expect_success '--show-origin blob ref' ' ' test_expect_success '--show-origin with --default' ' - test_must_fail git config --show-origin --default foo some.key + 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' '
@@ -2103,7 +2105,7 @@ test_expect_success '--show-scope with --show-origin' ' test_expect_success '--show-scope with --default' ' git config --show-scope --default foo some.key >actual && - echo "unknown foo" >expect && + echo "command foo" >expect && test_cmp expect actual '
Signature · 1 line
gitgitgadget
PATCH v2 10/14 trace2: plumb config kvi
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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".
- 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.
--- 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(-)
config.c +0 -46
@@ -78,16 +78,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
@@ -118,19 +108,9 @@ static inline struct config_source *config_reader_pop_source(struct config_readestatic 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;
@@ -404,18 +384,12 @@ 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, &opts); - -config_reader_set_scope (inc->config_reader, store_scope); } static int forbid_remote_url(const char *var, const char *value UNUSED,
@@ -2242,7 +2216,6 @@ static int do_git_config_sequence(struct config_reader *reader,char *xdg_config =NULL ;char *user_config =NULL ;char *repo_config; -enum config_scope prev_parsing_scope = reader->parsing_scope;if (opts->commondir) repo_config =mkpathdup ("%s/config" , opts->commondir);
@@ -2251,7 +2224,6 @@ static int do_git_config_sequence(struct config_reader *reader,else repo_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 ))
@@ -2259,7 +2231,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 ))
@@ -2270,13 +2241,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 && repository_format_worktree_config) {char *path =git_pathdup ("config.worktree" );if (!access_or_die (path,R_OK ,0 ))
@@ -2286,11 +2255,9 @@ static int do_git_config_sequence(struct config_reader *reader,free (path); } -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);
@@ -2303,7 +2270,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) {
@@ -2316,9 +2282,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.
@@ -2342,7 +2305,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; }
@@ -4045,14 +4007,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;
config.h +0 -1
@@ -366,7 +366,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);
trace2.c +2 -2
@@ -632,7 +632,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,struct key_value_info *kvi) {struct tr2_tgt *tgt_j;int j;
@@ -642,7 +642,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)
trace2.h +2 -1
@@ -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,struct key_value_info *kvi);#define trace2_def_param (param, value) \ trace2_def_param_fl(__FILE__, __LINE__, (param), (value))
trace2/tr2_cfg.c +6 -3
@@ -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, - struct key_value_info *kvi UNUSED, void *d) +struct key_value_info *kvi,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, + 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 = {0 };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); } }
trace2/tr2_tgt.h +3 -1
@@ -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, +struct key_value_info *kvi);typedef void (tr2_tgt_evt_repo_fl_t )(const char *file,int line,const struct repository *repo);
trace2/tr2_tgt_event.c +2 -2
@@ -476,11 +476,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,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 );
trace2/tr2_tgt_normal.c +2 -2
@@ -296,10 +296,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,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,
trace2/tr2_tgt_perf.c +2 -2
@@ -438,12 +438,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,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);
Signature · 1 line
gitgitgadget
PATCH v2 12/14 config.c: remove config_reader from configsets
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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.
--- config.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-)
config.c +10 -31
@@ -2285,8 +2285,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;
@@ -2378,7 +2377,6 @@ static int configset_find_element(struct config_set *set, const char *key, }static int configset_add_value (struct key_value_info *kvi_p, -struct config_reader *reader,struct config_set *set,const char *key,const char *value) {
@@ -2409,11 +2407,7 @@ static int configset_add_value(struct key_value_info *kvi_p, l_item->e = e; l_item->value_index = e->value_list.nr -1 ; -if (reader->source->name) { -kvi_from_source (reader->source, kvi_p->scope, kv_info); - }else { -kvi_from_param (kv_info); - } +memcpy (kv_info, kvi_p,sizeof (struct key_value_info )); si->util = kv_info;return 0 ;
@@ -2461,26 +2455,17 @@ 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,struct key_value_info *kvi,void *cb) { -struct configset_add_data *data = cb; -configset_add_value (kvi, data->config_reader, data->config_set, key, value); +struct config_set *set = cb; +configset_add_value (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,
@@ -2646,7 +2631,6 @@ int git_configset_get_pathname(struct config_set *set, const char *key, const chstatic 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;
@@ -2658,10 +2642,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 , &opts) <0 ) +if (config_with_options (config_set_callback, repo->config,NULL , + &opts) <0 )/* * config_with_options() normally returns only * zero, as most errors are fatal, and
@@ -2693,7 +2675,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)
@@ -2800,19 +2782,16 @@ 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 , &opts); +config_with_options (config_set_callback, &protected_config,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' */
Signature · 1 line
gitgitgadget
PATCH v2 13/14 config: add kvi.path, use it to evaluate includes
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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".
--- config.c | 41 +++++++++++++++++++---------------------- config.h | 1 + 2 files changed, 20 insertions(+), 22 deletions(-)
config.c +19 -22
@@ -154,7 +154,6 @@ struct config_include_data {void *data;const struct config_options *opts;struct git_config_source *config_source; -struct config_reader *config_reader;/* * All remote URLs discovered when reading all config files.
@@ -173,9 +172,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, -struct key_value_info *kvi, -const char *path, +static int handle_path_include (struct key_value_info *kvi,const char *path,struct config_include_data *inc) {int ret =0 ;
@@ -197,14 +194,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; }
@@ -212,8 +209,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 ?"<unknown>" : - cs->name ? cs->name : + !kvi ?"<unknown>" : + kvi->filename ? kvi->filename :"the command line" ); ret =git_config_from_file_with_options (git_config_include, path, inc, kvi->scope,NULL );
@@ -231,7 +228,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 (struct key_value_info *kvi,struct strbuf *pat) {struct strbuf path =STRBUF_INIT ;
@@ -248,11 +245,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?" );
@@ -267,7 +264,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 (struct key_value_info *kvi,const struct config_options *opts,const char *cond,size_t cond_len,int icase) {
@@ -284,7 +281,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 )
@@ -419,16 +416,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 (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,
@@ -443,7 +440,6 @@ static int git_config_include(const char *var, const char *value, struct key_value_info *kvi, 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;
@@ -457,16 +453,16 @@ static int git_config_include(const char *var, const char *value,return ret;if (!strcmp (var,"include.path" )) - ret =handle_path_include (cs, kvi, value, inc); + ret =handle_path_include (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 (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, kvi, value, inc); + ret =handle_path_include (kvi, value, inc); inc->fn = old_fn; }
@@ -648,6 +644,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,
@@ -1048,6 +1045,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,
@@ -2254,7 +2252,6 @@ int config_with_options(config_fn_t fn, void *data, inc.data = data; inc.opts = opts; inc.config_source = config_source; - inc.config_reader = &the_reader; fn = git_config_include; data = &inc; }
config.h +1 -0
@@ -116,6 +116,7 @@ struct key_value_info {int linenr;enum config_origin_type origin_type;enum config_scope scope; +const char *path; };/**
Signature · 1 line
gitgitgadget
PATCH v2 14/14 config: pass source to config_parser_event_fn_t
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
..so that the callback can use a "struct config_source" parameter instead of "config_reader.source". "struct config_source" is internal to config.c, but this refactor 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.
--- config.c | 77 ++++++++++---------------------------------------------- config.h | 6 +++++ 2 files changed, 19 insertions(+), 64 deletions(-)
config.c +13 -64
@@ -59,40 +59,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;
@@ -738,14 +704,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 = {0 }; - 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;
@@ -802,7 +763,6 @@ out:strbuf_release (&envvar);strvec_clear (&to_free);free (envw); -config_reader_pop_source (&the_reader);return ret; }
@@ -1028,7 +988,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;
@@ -1986,8 +1946,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) {
@@ -2000,21 +1959,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,
@@ -2033,7 +1988,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; }
@@ -2041,8 +1996,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,
@@ -2056,9 +2011,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;
@@ -2089,7 +2043,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,
@@ -2182,8 +2136,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,config_fn_t fn,void *data) {int ret =0 ;
@@ -2272,7 +2225,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, fn, data); + ret =do_git_config_sequence (opts, fn, data); }if (inc.remote_urls) {
@@ -2978,7 +2931,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;
@@ -3024,11 +2976,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;
@@ -3349,8 +3300,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)
config.h +6 -0
@@ -73,6 +73,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.
@@ -82,6 +83,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 {
@@ -101,6 +103,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 {
Signature · 1 line
gitgitgadget
PATCH v2 11/14 config: pass kvi to die_bad_number()
In reply to Glen Choo via GitGitGadgetFrom: Glen Choo <[email protected]>
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_<type>() can pass it to git_config_<type>().
Outside of config.c, config callbacks now need to pass "kvi" to any of the git_config_<type>() functions that parse a config string into a number type. Included is a .cocci patch to make that refactor. In cases where "kvi" would never be used, pass NULL, e.g.:
- In config.c, when we are parsing a boolean instead of a number
- In builtin/config.c, when calling normalize_value() before setting config to something the user gave us.
--- archive-tar.c | 4 +- builtin/commit-graph.c | 4 +- builtin/commit.c | 10 +- builtin/config.c | 20 +-- 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 | 153 ++++++++------------- config.h | 14 +- contrib/coccinelle/git_config_number.cocci | 27 ++++ diff.c | 9 +- fmt-merge-msg.c | 2 +- help.c | 5 +- http.c | 10 +- imap-send.c | 2 +- sequencer.c | 22 +-- setup.c | 2 +- submodule-config.c | 15 +- submodule-config.h | 3 +- t/helper/test-config.c | 6 +- upload-pack.c | 12 +- worktree.c | 2 +- 27 files changed, 182 insertions(+), 186 deletions(-) create mode 100644 contrib/coccinelle/git_config_number.cocci
archive-tar.c +2 -2
@@ -411,14 +411,14 @@ static int tar_filter_config(const char *var, const char *value, }static int git_tar_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *cb) +struct key_value_info *kvi,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, kvi); }return 0 ; }
builtin/commit-graph.c +2 -2
@@ -185,11 +185,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, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi, 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, kvi);/* * No need to fall-back to 'git_default_config', since this was already * called in 'cmd_commit_graph()'.
builtin/commit.c +6 -4
@@ -1412,7 +1412,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, kvi, + &is_bool);if (is_bool && s->submodule_summary) s->submodule_summary =-1 ;return 0 ;
@@ -1472,11 +1473,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, kvi);return 0 ; }if (!strcmp (k,"status.renamelimit" )) { - s->rename_limit =git_config_int (k, v); + s->rename_limit =git_config_int (k, v, kvi);return 0 ; }if (!strcmp (k,"diff.renames" )) {
@@ -1622,7 +1623,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, kvi, + &is_bool);return 0 ; }
builtin/config.c +11 -9
@@ -254,13 +254,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
@@ -414,7 +415,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 ;
@@ -429,12 +431,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
@@ -876,7 +878,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 ],NULL ); 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"
@@ -885,7 +887,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 ],NULL ); ret =git_config_set_multivar_in_file_gently (given_config_source.file, argv[0 ], value, argv[2 ], flags);
@@ -893,7 +895,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 ],NULL ); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, CONFIG_REGEX_NONE,
@@ -902,7 +904,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 ],NULL ); ret =git_config_set_multivar_in_file_gently (given_config_source.file, argv[0 ], value, argv[2 ], flags |CONFIG_FLAGS_MULTI_REPLACE );
builtin/fetch.c +2 -2
@@ -125,7 +125,7 @@ static int git_fetch_config(const char *k, const char *v, }if (!strcmp (k,"submodule.fetchjobs" )) { - submodule_fetch_jobs_config =parse_submodule_fetchjobs (k, v); + submodule_fetch_jobs_config =parse_submodule_fetchjobs (k, v, kvi);return 0 ; }else if (!strcmp (k,"fetch.recursesubmodules" )) { recurse_submodules =parse_fetch_recurse_submodules_arg (k, v);
@@ -133,7 +133,7 @@ static int git_fetch_config(const char *k, const char *v, }if (!strcmp (k,"fetch.parallel" )) { - fetch_parallel_config =git_config_int (k, v); + fetch_parallel_config =git_config_int (k, v, kvi);if (fetch_parallel_config <0 )die (_ ("fetch.parallel cannot be negative" ));if (!fetch_parallel_config)
builtin/fsmonitor--daemon.c +3 -3
@@ -40,7 +40,7 @@ static int fsmonitor_config(const char *var, const char *value, struct key_value_info *kvi, void *cb) {if (!strcmp (var,FSMONITOR__IPC_THREADS )) { -int i =git_config_int (var, value); +int i =git_config_int (var, value, kvi);if (i <1 )return error (_ ("value of '%s' out of range: %d" ),FSMONITOR__IPC_THREADS , i);
@@ -49,7 +49,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, kvi);if (i <0 )return error (_ ("value of '%s' out of range: %d" ),FSMONITOR__START_TIMEOUT , i);
@@ -59,7 +59,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, kvi, &is_bool);if (i <0 )return error (_ ("value of '%s' not bool or int: %d" ), var, i);
builtin/grep.c +1 -1
@@ -298,7 +298,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, kvi);if (num_threads <0 )die (_ ("invalid number of threads specified (%d) for %s" ), num_threads, var);
builtin/index-pack.c +2 -2
@@ -1584,13 +1584,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, 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, kvi);if (nr_threads <0 )die (_ ("invalid number of threads specified (%d)" ), nr_threads);
builtin/log.c +1 -1
@@ -569,7 +569,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, kvi);return 0 ; }if (!strcmp (var,"format.encodeemailheaders" )) {
builtin/pack-objects.c +7 -7
@@ -3138,23 +3138,23 @@ static int git_pack_config(const char *k, const char *v, struct key_value_info *kvi, void *cb) {if (!strcmp (k,"pack.window" )) { - window =git_config_int (k, v); + window =git_config_int (k, v, kvi);return 0 ; }if (!strcmp (k,"pack.windowmemory" )) { - window_memory_limit =git_config_ulong (k, v); + window_memory_limit =git_config_ulong (k, v, kvi);return 0 ; }if (!strcmp (k,"pack.depth" )) { - depth =git_config_int (k, v); + depth =git_config_int (k, v, 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, 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, kvi);return 0 ; }if (!strcmp (k,"pack.writebitmaphashcache" )) {
@@ -3180,7 +3180,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, kvi);if (delta_search_threads <0 )die (_ ("invalid number of threads specified (%d)" ), delta_search_threads);
@@ -3191,7 +3191,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, kvi);if (pack_idx_opts.version >2 )die (_ ("bad pack.indexVersion=%" PRIu32), pack_idx_opts.version);
builtin/receive-pack.c +5 -5
@@ -154,12 +154,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, 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, kvi);return 0 ; }
@@ -227,7 +227,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, kvi);return 0 ; }
@@ -242,12 +242,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, 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, kvi);return 0 ; }
builtin/submodule--helper.c +2 -2
@@ -2187,13 +2187,13 @@ static int update_clone_task_finished(int result, }static int git_update_clone_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi,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, kvi);return 0 ; }
config.c +57 -96
376 lines not on this page · raw message
config.h +8 -6
@@ -229,22 +229,23 @@ 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 *,struct key_value_info *); -int64_t git_config_int64 (const char *,const char *); +int64_t git_config_int64 (const char *,const char *,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 *,struct key_value_info *); -ssize_t git_config_ssize_t (const char *,const char *); +ssize_t git_config_ssize_t (const char *,const char *,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 *,struct key_value_info *, +int *);/** * Parse a string into a boolean value, respecting keywords like "true" and
@@ -509,7 +510,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);
contrib/coccinelle/git_config_number.cocci new file +27 -0
@@ -0,0 +1,27 @@ +@@ +identifier C1, C2, C3; +@@ +( +( +git_config_int +| +git_config_int64 +| +git_config_ulong +| +git_config_ssize_t +) + (C1, C2 ++ , kvi + ) +| +( +git_configset_get_value +| +git_config_bool_or_int +) + (C1, C2, ++ kvi, + C3 + ) +)
diff.c +5 -4
@@ -372,13 +372,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, 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, + kvi);if (diff_interhunk_context_default <0 )return -1 ;return 0 ;
@@ -404,7 +405,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, kvi);return 0 ; }if (!strcmp (var,"diff.external" ))
@@ -443,7 +444,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, kvi);return 0 ; }
fmt-merge-msg.c +1 -1
@@ -24,7 +24,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, kvi, &is_bool);if (!is_bool && merge_log_config <0 )return error ("%s: negative length %s" , key, value);if (is_bool && merge_log_config)
help.c +2 -3
@@ -545,8 +545,7 @@ static struct cmdnames aliases;#define AUTOCORRECT_IMMEDIATELY (-1)static int git_unknown_cmd_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, - void *cb UNUSED) + struct key_value_info *kvi, void *cb UNUSED) {const char *p;
@@ -560,7 +559,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, kvi); autocorrect = (v <0 ) ?AUTOCORRECT_IMMEDIATELY : v; }
http.c +5 -5
@@ -412,21 +412,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, 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, 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, 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, kvi);return 0 ; }
@@ -462,7 +462,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, 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 )
imap-send.c +1 -1
@@ -1341,7 +1341,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, kvi);else if (!strcmp ("imap.host" , var)) {if (!val) {git_die_config ("imap.host" ,"Missing value for 'imap.host'" );
sequencer.c +11 -11
@@ -2878,7 +2878,7 @@ static int git_config_string_dup(char **dest, }static int populate_opts_cb (const char *key,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,void *data) {struct replay_opts *opts = data;int error_flag =1 ;
@@ -2886,26 +2886,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, 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, 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, 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, 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, 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, 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, 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, kvi, &error_flag);else if (!strcmp (key,"options.mainline" )) - opts->mainline =git_config_int (key, value); + opts->mainline =git_config_int (key, value, kvi);else if (!strcmp (key,"options.strategy" ))git_config_string_dup (&opts->strategy, key, value);else if (!strcmp (key,"options.gpg-sign" ))
@@ -2915,7 +2915,7 @@ static int populate_opts_cb(const char *key, const char *value, opts->xopts[opts->xopts_nr++] =xstrdup (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, kvi, &error_flag) ?RERERE_AUTOUPDATE :RERERE_NOAUTOUPDATE ;else if (!strcmp (key,"options.default-msg-cleanup" )) { opts->explicit_cleanup =1 ;
setup.c +1 -1
@@ -594,7 +594,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, kvi);else if (skip_prefix (var,"extensions." , &ext)) {switch (handle_extension_v0 (var, value, ext, data)) {case EXTENSION_ERROR :
submodule-config.c +7 -8
@@ -302,9 +302,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, +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)
@@ -848,14 +849,13 @@ struct fetch_config { };static int gitmodules_fetch_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, -void *cb) +struct key_value_info *kvi,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, kvi);return 0 ; }else if (!strcmp (var,"fetch.recursesubmodules" )) {if (config->recurse_submodules)
@@ -877,12 +877,11 @@ void fetch_config_from_gitmodules(int *max_children, int *recurse_submodules) }static int gitmodules_update_clone_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, -void *cb) +struct key_value_info *kvi,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, kvi);return 0 ; }
submodule-config.h +2 -1
@@ -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, +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,
t/helper/test-config.c +3 -3
@@ -61,12 +61,12 @@ static int iterate_cb(const char *var, const char *value, }static int parse_int_cb (const char *var,const char *value, - struct key_value_info *kvi UNUSED, void *data) +struct key_value_info *kvi,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, kvi);printf ("%d\n" , parsed); }return 0 ;
@@ -179,7 +179,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
upload-pack.c +7 -5
@@ -1264,7 +1264,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) +struct key_value_info *kvi, +struct upload_pack_data *data) {struct strbuf buf =STRBUF_INIT ;const char *sub, *key;
@@ -1291,7 +1292,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);
@@ -1299,7 +1301,7 @@ static int parse_object_filter_config(const char *var, const char *value, }static int upload_pack_config (const char *var,const char *value, - struct key_value_info *kvi UNUSED, +struct key_value_info *kvi,void *cb_data) {struct upload_pack_data *data = cb_data;
@@ -1320,7 +1322,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, kvi);if (!data->keepalive) data->keepalive =-1 ; }else if (!strcmp ("uploadpack.allowfilter" , var)) {
@@ -1335,7 +1337,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, kvi, data) <0 )return -1 ;return parse_hide_refs_config (var, value,"uploadpack" , &data->hidden_refs);
worktree.c +1 -1
@@ -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)))
Signature · 1 line
gitgitgadget
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
In reply to Glen Choo via GitGitGadgetHi Glen
Quoted 5 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
..without actually changing any of its implementations. This commit does not build - I've split this out for readability, but post-RFC I will squash this with the rest of the refactor + cocci changes.
While this ends up with a huge amount of churn, I think that is probably inevitable if we're going to get rid of global state (I see Ævar suggested adding a separate set of callbacks but I'm not sure how that would work with chaining up to git_default_config() and it would be nice to improve our error messages with filename and line information). I've not been following this thread all that closely but a couple of thoughts crossed by mind.
- is it worth making struct key_value_info opaque and provide getters for the fields so we can change the implementation in the future without having to modify every user. We could rename it config_context or something generic like that if we think it might grow in scope in the future.
- (probably impractical) could we stuff the key and value into struct key_value_info so config_fn_t becomes
fn(const struct key_value_info, void *data)
that would get rid of all the UNUSED annotations but would mean even more churn. The advantage is that one could add functions like kvi_bool_or_int(kvi, &is_bool) and get good error messages because all the config parsing functions would all have access to location information.
Best Wishes
Phillip
Quoted 241 lines
Signed-off-by Glen Choo <[email protected]>--- config.c | 8 +- config.h | 16 +- .../coccinelle/config_fn_kvi.pending.cocci | 146 ++++++++++++++++++ 3 files changed, 158 insertions(+), 12 deletions(-)create mode 100644
contrib/coccinelle/config_fn_kvi.pending.cocciconfig.c +4
-4@@ -489,7 +489,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;@@ -671,7 +671,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; }@@ -959,7 +959,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;@@ -2303,7 +2303,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);config.h +8
-8@@ -111,6 +111,13 @@ struct config_options { } error_action; }; +struct key_value_info { +const char *filename; +int linenr; +enum config_origin_type origin_type; +enum config_scope scope; +}; +/** * A config callback function takes three parameters: * @@ -129,7 +136,7 @@ struct config_options {* A config callback should return 0 for success, or -1 if the variable * could not be parsed properly. */ -typedef int (*config_fn_t )(const char *,const char *,void *); +typedef int (*config_fn_t )(const char *,const char *,struct key_value_info *,void *);int git_default_config (const char *,const char *,void *);@@ -667,13 +674,6 @@ int git_config_get_expiry(const char *key, const char **output);/* parse either "this many days" integer, or "5.days.ago" approxidate */ int git_config_get_expiry_in_days (const char *key,timestamp_t *,timestamp_t now); -struct key_value_info { -const char *filename; -int linenr; -enum config_origin_type origin_type; -enum config_scope scope; -}; -/** * First prints the error message specified by the caller in `err` and then * dies printing the line number and the file name of the highest priority contrib/coccinelle/config_fn_kvi.pending.cocci new file +146
-0@@ -0,0 +1,146 @@ +// These are safe to apply to *.c *.h builtin/*.c + +@ get_fn @ +identifier fn, R; +@@ +( +( +git_config_from_file +| +git_config_from_file_with_options +| +git_config_from_mem +| +git_config_from_blob_oid +| +read_early_config +| +read_very_early_config +| +config_with_options +| +git_config +| +git_protected_config +| +config_from_gitmodules +) + (fn, ...) +| +repo_config(R, fn, ...) +) + +@ extends get_fn @ +identifier C1, C2, D; +@@ +int fn(const char *C1, const char *C2, ++ struct key_value_info *kvi, + void *D); + +@ extends get_fn @ +@@ +int fn(const char *, const char *, ++ struct key_value_info *, + void *); + +@ extends get_fn @ +// Don't change fns that look like callback fns but aren't +identifier fn2 != tar_filter_config && != git_diff_heuristic_config && + != git_default_submodule_config && != git_color_config && + != bundle_list_update && != parse_object_filter_config; +identifier C1, C2, D1, D2, S; +attribute name UNUSED; +@@ +int fn(const char *C1, const char *C2, ++ struct key_value_info *kvi, + void *D1) { +<+... +( +fn2(C1, C2, ++ kvi, +D2); +| +if(fn2(C1, C2, ++ kvi, +D2) < 0) { ... } +| +return fn2(C1, C2, ++ kvi, +D2); +| +S = fn2(C1, C2, ++ kvi, +D2); +) +...+> + } + +@ extends get_fn@ +identifier C1, C2, D; +attribute name UNUSED; +@@ +int fn(const char *C1, const char *C2, ++ struct key_value_info *kvi UNUSED, + void *D) {...} + + +// The previous rules don't catch all callbacks, especially if they're defined +// in a separate file from the git_config() call. Fix these manually. +@@ +identifier C1, C2, D; +attribute name UNUSED; +@@ +int +( +git_ident_config +| +urlmatch_collect_fn +| +write_one_config +| +forbid_remote_url +| +credential_config_callback +) + (const char *C1, const char *C2, ++ struct key_value_info *kvi UNUSED, + void *D) {...} + +@@ +identifier C1, C2, D, D2, S, fn2; +@@ +int +( +http_options +| +git_status_config +| +git_commit_config +| +git_default_core_config +| +grep_config +) + (const char *C1, const char *C2, ++ struct key_value_info *kvi, + void *D) { +<+... +( +fn2(C1, C2, ++ kvi, +D2); +| +if(fn2(C1, C2, ++ kvi, +D2) < 0) { ... } +| +return fn2(C1, C2, ++ kvi, +D2); +| +S = fn2(C1, C2, ++ kvi, +D2); +) +...+> + }
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
Quoted 5 lines · Phillip Wood
- is it worth making struct
key_value_infoopaque and provide getters for the fields so we can change the implementation in the future without having to modify every user. We could rename itconfig_contextor something generic like that if we think it might grow in scope in the future.
Yes! I planned to do the key_value_info -> config_context conversion when I send the first non-RFC version for this exact reason.
Quoted 5 lines
- (probably impractical) could we stuff the key and value into struct
key_value_infosoconfig_fn_tbecomes
fn(const struct key_value_info, void *data)
that would get rid of all the UNUSED annotations but would mean even more churn.
Some of my colleagues also suggested this off-list. I think it is impractical for this series because I don't think anyone could reasonably review with all of the added churn. At least its current form, the churn is mostly concentrated in the signatures, but performing ^this change would make the bodies quite churny too.
After this series, I think it becomes somewhat feasible with coccinelle. My .cocci files were difficult to craft because we couldn't rely on the signature of config_fn_t alone to tell us if the function is actually used as config_fn_t, but after this series, we can just use the signature since config_fn_t has a struct key_value_info param.
Quoted 4 lines
The advantage is that one could add functions like
kvi_bool_or_int(kvi, &is_bool)and get good error messages because all the config parsing functions would all have access to location information.
Interesting, I hadn't considered this possibility. This seems like a pretty good abstraction to me, though I worry about the feasibility since this is yet again more churn.
Re: [PATCH v2 05/14] (RFC-only) config: finish config_fn_t refactor
In reply to Glen Choo via GitGitGadgetQuoted 3 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
Here's an exhaustive list of all of the changes:
Up to here the changes are all mechanical, and look good.
Re: [PATCH v2 06/14] config.c: pass kvi in configsets
In reply to Glen Choo via GitGitGadgetQuoted 5 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
Trivially pass "struct
key_value_info" to config callbacks inconfigset_iter(). Then, in config callbacks that are only used with configsets, use the "kvi" arg to replace calls to current_config_*(),
OK, so the end result of this patch is, indeed, that configset_iter() passes kvi, and this is proven by some callbacks being changed to use the kvi provided, and still functioning. I did not verify that the callbacks in this patch were the *only* callbacks that are only used with configsets, but I don't think that is important for the purpose of reviewing this patch - as long as current_config_* has all been removed at the end of this patchset, then things are fine.
Quoted 1 line
and delete
current_config_line()because it has no remaining callers.
Ah, great that we can remove one of the global-reliant functions as a result of this.
Re: [PATCH v2 07/14] config: provide kvi with config files
In reply to Glen Choo via GitGitGadgetQuoted 1 line · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
For some reason, I was having difficulty understanding the commit message, so I looked at the code and I think I could reason out the purpose of this patch. It is 2-fold:
- teach git_config_from_file_with_options() to supply information to its callbacks through a kvi argument
- its kvi argument requires a scope; get it not through current_config_scope() but through an argument
And as a corollary of the latter point, the scope is UNKNOWN when no global scope is set by the surrounding code (if a scope is set by the surrounding code, use that instead).
Unlike the previous patch, since no callers were changed, the only way we can see that this has happened is through reading the code of git_config_from_file_with_options(), but I've read it and it looks good. (Again, as long as current_config_* is all gone at the end of the patch set, then things are fine.)
Quoted 11 lines
Refactor out the configset logic that caches "struct
config_source" and "enumconfig_scope" as a "structkey_value_info", and use it to pass the "kvi" arg to config callbacks when parsing config files. Get the "enumconfig_scope" value by plumbing an additional arg throughgit_config_from_file_with_options()and the underlying machinery.We do not exercise the "kvi" arg 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 "kvi" yet.Signed-off-by Glen Choo <[email protected]>
Now that I reread this, I can see that it hit all the points that I wrote at the top. So I think no change is needed in the commit message, unless another reviewer also found it unclear.
The code itself looks good.
Re: [PATCH v2 09/14] config.c: provide kvi with CLI config
In reply to Glen Choo via GitGitGadgetQuoted 5 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
plumb "kvi" so that we can replace
nearly all calls to current_config_*(). (The exception is an edge case where trace2/*.c callscurrent_config_scope().
Probably clearer to say:
plumb "kvi" so that we can remove all calls of current_config_scope() except from trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls).
Quoted 13 lines
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.* "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration. Fix this by copying the "kvi" arg 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" (we don't allow this combination of args because of this bug), but that is left unchanged for now.
Quoted 6 lines
* "git config --default" doesn't have config source metadata when displaying the default value. 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().Signed-off-by Glen Choo <[email protected]>
Thanks for noticing and fixing these.
builtin/config.c static int urlmatch_collect_fn(const char *var, const char *value, · line 580
Quoted 1 line
builtin/config.c +1
-0+memcpy (&matched->kvi, kvi,sizeof (struct key_value_info ));
Can this just be
matched->kvi = *kvi;
?
If not, for the sizeof, use *kvi as the argument instead of struct key_value_info.
Re: [PATCH v2 10/14] trace2: plumb config kvi
In reply to Glen Choo via GitGitGadgetQuoted 1 line · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
Thanks - a mechanical code change that allows for quite some code to be removed. Looks good.
Re: [PATCH v2 11/14] config: pass kvi to die_bad_number()
In reply to Glen Choo via GitGitGadgetQuoted 8 lines · Glen Choo via GitGitGadget
Outside of
config.c, config callbacks now need to pass "kvi" to any of the git_config_<type>() functions that parse a config string into a number type. Included is a .cocci patch to make that refactor. In cases where "kvi" would never be used, pass NULL, e.g.:- In
config.c, when we are parsing a boolean instead of a number
- Inbuiltin/config.c, when callingnormalize_value()before setting config to something the user gave us.
In these cases, could we synthesize a kvi instead of using NULL? I believe there are already code paths that use an UNKNOWN scope - these seem similar to that.
Otherwise looks good - a straightforward, mostly mechanical, change.
Re: [PATCH v2 07/14] config: provide kvi with config files
In reply to Glen Choo via GitGitGadgetconfig.c static int get_value(struct config_source *cs, config_fn_t fn, void *data, · line 969
Quoted 7 lines · Glen Choo via GitGitGadget
config.c +2
-1@@ -963,7 +965,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, kvi, data);
Forgot to mention in my other email...it's a pity that we have to bump the kvi->linenr like this because the original kvi generated from the cs is now out-to-date w.r.t. the cs in terms of line number (you can see in the context how the cs linenr is also updated), so there are now 2 sources of truth with regards to the line number. I can't think of a better way to do this, though.
Re: [PATCH v2 13/14] config: add kvi.path, use it to evaluate includes
In reply to Glen Choo via GitGitGadgetQuoted 6 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
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".
Maybe add:
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.
The code change looks good.
Re: [PATCH v2 14/14] config: pass source to config_parser_event_fn_t
In reply to Glen Choo via GitGitGadgetQuoted 6 lines · Glen Choo via GitGitGadget
From: Glen Choo <[email protected]>
..so that the callback can use a "struct
config_source" parameter instead of "config_reader.source". "structconfig_source" is internal toconfig.c, but this refactor is okay because this function has only ever been (and probably ever will be) used internally byconfig.c.
Maybe s/this refactor/adding a pointer to a struct defined in a .c into a public function signature defined in a .h/
So this means that callers cannot instantiate that public function unless they are in config.c, but I see that it has been appropriately documented, so it should be fine.
Thanks for this series. Overall I had some minor comments, but things look good overall.
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
In reply to Glen ChooQuoted 10 lines · Glen Choo
Quoted 5 lines · Phillip Wood
- is it worth making struct
key_value_infoopaque and provide getters for the fields so we can change the implementation in the future without having to modify every user. We could rename itconfig_contextor something generic like that if we think it might grow in scope in the future.Yes! I planned to do the
key_value_info->config_contextconversion when I send the first non-RFC version for this exact reason.
That's great
Quoted 11 lines
Quoted 5 lines
- (probably impractical) could we stuff the key and value into struct
key_value_infosoconfig_fn_tbecomes
fn(const struct key_value_info, void *data)
that would get rid of all the UNUSED annotations but would mean even more churn.Some of my colleagues also suggested this off-list. I think it is impractical for this series because I don't think anyone could reasonably review with all of the added churn. At least its current form, the churn is mostly concentrated in the signatures, but performing ^this change would make the bodies quite churny too.
I agree that keeping the churn to the function signatures makes it bearable. I wonder though if we could make the change by doing
-git_default_config(const char *key, const char *value, void *data) +git_default_config(const struct key_value_info *kvi, void *data)
{
+ const char *key = kvi_key(kvi);
+ const char *value = kvi_value(kvi);
+
That would add to the diffstat but I think it wouldn't really be any harder to review than just changing the signature as we're not modifying any existing lines in the function body, just adding a couple of variable declarations to the start of the function. If there is an error in either of the variable declarations then the compiler will complain as "key" or "value" will end up not being declared. It would pave the way for gradually changing the function bodies to use "kvi" directly and removing "key" and "value"
Quoted 5 lines
After this series, I think it becomes somewhat feasible with coccinelle. My .cocci files were difficult to craft because we couldn't rely on the signature of
config_fn_talone to tell us if the function is actually used asconfig_fn_t, but after this series, we can just use the signature sinceconfig_fn_thas a structkey_value_infoparam.
That's an interesting possibility, I worry though that two huge changes to the config callbacks might be one too many though.
Quoted 8 lines
Quoted 4 lines
The advantage is that one could add functions like
kvi_bool_or_int(kvi, &is_bool)and get good error messages because all the config parsing functions would all have access to location information.Interesting, I hadn't considered this possibility. This seems like a pretty good abstraction to me, though I worry about the feasibility since this is yet again more churn.
It could be done gradually though, converting one config callback at a time once the relevant changes have been made to config.c.
As an aside, I think we'd also want a couple of helpers for matching keys so we can just write kvi_match_key(kvi, "user.name") or kvi_skip_key_prefix(kvi, "core.", &p) rather than having to extract the key name first.
Best Wishes
Phillip
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
Quoted 9 lines · Phillip Wood
Quoted 5 lines
Some of my colleagues also suggested this off-list. I think it is impractical for this series because I don't think anyone could reasonably review with all of the added churn. At least its current form, the churn is mostly concentrated in the signatures, but performing ^this change would make the bodies quite churny too.
I agree that keeping the churn to the function signatures makes it bearable. I wonder though if we could make the change by doing
Review
Quoted 5 lines
(quoted diff) +3
-1-git_default_config(const char *key, const char *value, void *data) +git_default_config(const struct key_value_info *kvi, void *data) { + const char *key = kvi_key(kvi); + const char *value = kvi_value(kvi);
Ah, yes that seems reasonable to review (and most importantly for me, it is also doable with coccinelle once I figure out how :P). I also agree that it's better to do it all in one change than two.
Quoted 4 lines
As an aside, I think we'd also want a couple of helpers for matching keys so we can just write
kvi_match_key(kvi, "user.name")orkvi_skip_key_prefix(kvi, "core.", &p)rather than having to extract the key name first.
Yes, and that would also abstract over implementation details like matching keys using strcasecmp() and not strcmp(). For reasons like this, I think your proposal paves the way for a harder-to-misuse API.
I still have some nagging, probably irrational fear that consolidating all of the config_fn_t args is trickier to manage than adding a single key_value_info arg. It definitely *sounds* trickier, but I can't really think of a real downside.
Maybe I just have to try it and send the result for others to consider.
Re: [PATCH v2 14/14] config: pass source to config_parser_event_fn_t
In reply to Jonathan TanQuoted 2 lines · Jonathan Tan
Thanks for this series. Overall I had some minor comments, but things look good overall.
Thank you so much. I appreciate the thorough effort and all of the suggestions.
Re: [PATCH v2 11/14] config: pass kvi to die_bad_number()
In reply to Jonathan TanQuoted 6 lines · Jonathan Tan
Quoted 5 lines · Glen Choo via GitGitGadget
Outside of
config.c, config callbacks now need to pass "kvi" to any of the git_config_<type>() functions that parse a config string into a number type. Included is a .cocci patch to make that refactor. In cases where "kvi" would never be used, pass NULL, e.g.:
Quoted 7 lines
Quoted 3 lines
- In
config.c, when we are parsing a boolean instead of a number
- Inbuiltin/config.c, when callingnormalize_value()before setting config to something the user gave us.In these cases, could we synthesize a kvi instead of using NULL? I believe there are already code paths that use an UNKNOWN scope - these seem similar to that.
Okay, that sounds reasonable. This has echoes of Philip Wood's suggestion (elsewhere in the thread) of combining all of the config_fn_t args into a single struct, which means we can no longer use NULL as the default.
Re: [PATCH v2 09/14] config.c: provide kvi with CLI config
In reply to Jonathan TanQuoted 7 lines · Jonathan Tan
builtin/config.c static int urlmatch_collect_fn(const char *var, const char *value, · line 580
Quoted 1 line
builtin/config.c +1
-0+memcpy (&matched->kvi, kvi,sizeof (struct key_value_info ));Can this just be
matched->kvi = *kvi;?
If I remember correctly (big if), we have to copy the memory because the config machinery allocates kvi on the stack, and the relevant functions have returned by then. Hm, does this suggest that kvi should be const?
Quoted 2 lines
If not, for the sizeof, use *kvi as the argument instead of struct
key_value_info.
Makes sense.
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
In reply to Glen ChooQuoted 10 lines · Glen Choo
Quoted 4 lines · Phillip Wood
As an aside, I think we'd also want a couple of helpers for matching keys so we can just write
kvi_match_key(kvi, "user.name")orkvi_skip_key_prefix(kvi, "core.", &p)rather than having to extract the key name first.Yes, and that would also abstract over implementation details like matching keys using
strcasecmp()and notstrcmp(). For reasons like this, I think your proposal paves the way for a harder-to-misuse API.
Quoted 6 lines
I still have some nagging, probably irrational fear that consolidating all of the
config_fn_targs is trickier to manage than adding a singlekey_value_infoarg. It definitely *sounds* trickier, but I can't really think of a real downside.Maybe I just have to try it and send the result for others to consider.
That's probably the best way to see if it is an improvement - you can always blame me if it turns out not to be! Hopefully it isn't too much work to add enough api to be able to convert a couple of config_fn_t functions to see how it pans out.
Best Wishes
Phillip
Re: [PATCH v2 03/14] (RFC-only) config: add kvi arg to config_fn_t
Quoted 16 lines · Phillip Wood
Quoted 15 lines · Glen Choo
Quoted 4 lines · Phillip Wood
As an aside, I think we'd also want a couple of helpers for matching keys so we can just write
kvi_match_key(kvi, "user.name")orkvi_skip_key_prefix(kvi, "core.", &p)rather than having to extract the key name first.Yes, and that would also abstract over implementation details like matching keys using
strcasecmp()and notstrcmp(). For reasons like this, I think your proposal paves the way for a harder-to-misuse API.I still have some nagging, probably irrational fear that consolidating all of the
config_fn_targs is trickier to manage than adding a singlekey_value_infoarg. It definitely *sounds* trickier, but I can't really think of a real downside.
Quoted 7 lines
Quoted 1 line
Maybe I just have to try it and send the result for others to consider.
That's probably the best way to see if it is an improvement - you can always blame me if it turns out not to be! Hopefully it isn't too much work to add enough api to be able to convert a couple of
config_fn_tfunctions to see how it pans out.
I was preparing a reroll that incorporated some of the suggestions here, but when I was done, I didn't really feel like it was better (or at the very least, worth the extra churn) compared to the original approach.
The 3 versions I was comparing are:
1. Adding a new "struct config_context" arg to config_fn_t that only contains a .kvi member. This is basically the approach in v1 and v2 (adding an extra args) but wrapping it in a "struct config_context" so that we can grow it later.
2. Stuffing "key" and "value" into "struct key_value_info" and removing "key" and "value" from config_fn_t.
3. Creating a "struct config_context" that contains "key", "value" and "struct key_value_info" as separate members, and removing "key" and "value" from config_fn_t.
I didn't try using opaque getters - I think that's nice to have, but isn't crucial to this series and introduces a lot of churn.
I've uploaded an implementation of option 3. [1]. The result is quite ugly in some places. In particular, config callbacks are used to calling other config callbacks with slightly different args (e.g. massaging the "key" but keeping the "value" the same, see patches 3,5/14 for examples.), so to make this work, I ended up creating a new "config_context", copying over the relevant members, then changing the members that need to be different. I didn't pursue the refactor to its end state (e.g. some of the CLI config machinery in the earlier patches and git_config_int()/ functions that end in die_bad_number() in later patches, take "key", "value", "key_value_info" as separate args instead of a single "config_context" arg) so I haven't reaped all of the benefits, but I thought the range-diff was getting churny enough that I wasn't interested in pursuing the idea further.
I toyed with option 2 for a bit. Unsurprisingly, it requires even more copying of members, though in some ways, it's better than option 3 because callers only have to initialize one "struct key_value_info" instead of "struct key_value_info" _and_ "struct config_context". However, it requires reworking the machinery quite a lot because "key_value_info" is currently used _just_ for config source information, and there are several cases where we need to propagate the config source information separately from the key/value (e.g. the configsets store "key" in a hashmap key, "value" in a string_list_item.string, and "key_value_info" in a string_list_item.util). I'm convinced that this is better interface-wise than option 3, but the required effort is high enough that I don't think we should do this unless we see a real need for it.
With that in mind, I'm tempted to continue with option 1 for now, but let me know if I'm missing something.