From: Glen Choo <chooglen@xxxxxxxxxx> ..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. Signed-off-by: Glen Choo <chooglen@xxxxxxxxxx> --- 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 diff --git a/config.c b/config.c index 147e422a27b..758d6a5cc3b 100644 --- a/config.c +++ b/config.c @@ -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; } diff --git a/config.h b/config.h index 525fc0d5e03..2c7b7399691 100644 --- a/config.h +++ b/config.h @@ -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 diff --git a/contrib/coccinelle/config_fn_kvi.pending.cocci b/contrib/coccinelle/config_fn_kvi.pending.cocci new file mode 100644 index 00000000000..d4c84599afa --- /dev/null +++ b/contrib/coccinelle/config_fn_kvi.pending.cocci @@ -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); +) +...+> + } -- gitgitgadget