Git fork

config: add ctx arg to config_fn_t

Add a new "const struct config_context *ctx" arg to config_fn_t to hold
additional information about the config iteration operation.
config_context has a "struct key_value_info kvi" member that holds
metadata about the config source being read (e.g. what kind of config
source it is, the filename, etc). In this series, we're only interested
in .kvi, so we could have just used "struct key_value_info" as an arg,
but config_context makes it possible to add/adjust members in the future
without changing the config_fn_t signature. We could also consider other
ways of organizing the args (e.g. moving the config name and value into
config_context or key_value_info), but in my experiments, the
incremental benefit doesn't justify the added complexity (e.g. a
config_fn_t will sometimes invoke another config_fn_t but with a
different config value).

In subsequent commits, the .kvi member will replace the global "struct
config_reader" in config.c, making config iteration a global-free
operation. It requires much more work for the machinery to provide
meaningful values of .kvi, so for now, merely change the signature and
call sites, pass NULL as a placeholder value, and don't rely on the arg
in any meaningful way.

Most of the changes are performed by
contrib/coccinelle/config_fn_ctx.pending.cocci, which, for every
config_fn_t:

- Modifies the signature to accept "const struct config_context *ctx"
- Passes "ctx" to any inner config_fn_t, if needed
- Adds UNUSED attributes to "ctx", if needed

Most config_fn_t instances are easily identified by seeing if they are
called by the various config functions. Most of the remaining ones are
manually named in the .cocci patch. Manual cleanups are still needed,
but the majority of it is trivial; it's either adjusting config_fn_t
that the .cocci patch didn't catch, or adding forward declarations of
"struct config_context ctx" to make the signatures make sense.

The non-trivial changes are in cases where we are invoking a config_fn_t
outside of config machinery, and we now need to decide what value of
"ctx" to pass. These cases are:

- trace2/tr2_cfg.c:tr2_cfg_set_fl()

This is indirectly called by git_config_set() so that the trace2
machinery can notice the new config values and update its settings
using the tr2 config parsing function, i.e. tr2_cfg_cb().

- builtin/checkout.c:checkout_main()

This calls git_xmerge_config() as a shorthand for parsing a CLI arg.
This might be worth refactoring away in the future, since
git_xmerge_config() can call git_default_config(), which can do much
more than just parsing.

Handle them by creating a KVI_INIT macro that initializes "struct
key_value_info" to a reasonable default, and use that to construct the
"ctx" arg.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Glen Choo and committed by
Junio C Hamano
a4e7e317 e0f9a51c

+515 -181
+2 -1
alias.c
··· 12 12 struct string_list *list; 13 13 }; 14 14 15 - static int config_alias_cb(const char *key, const char *value, void *d) 15 + static int config_alias_cb(const char *key, const char *value, 16 + const struct config_context *ctx UNUSED, void *d) 16 17 { 17 18 struct config_alias_data *data = d; 18 19 const char *p;
+2 -1
archive-tar.c
··· 411 411 return 0; 412 412 } 413 413 414 - static int git_tar_config(const char *var, const char *value, void *cb) 414 + static int git_tar_config(const char *var, const char *value, 415 + const struct config_context *ctx UNUSED, void *cb) 415 416 { 416 417 if (!strcmp(var, "tar.umask")) { 417 418 if (value && !strcmp(value, "user")) {
+1
archive-zip.c
··· 617 617 } 618 618 619 619 static int archive_zip_config(const char *var, const char *value, 620 + const struct config_context *ctx UNUSED, 620 621 void *data UNUSED) 621 622 { 622 623 return userdiff_config(var, value);
+3 -2
builtin/add.c
··· 357 357 OPT_END(), 358 358 }; 359 359 360 - static int add_config(const char *var, const char *value, void *cb) 360 + static int add_config(const char *var, const char *value, 361 + const struct config_context *ctx, void *cb) 361 362 { 362 363 if (!strcmp(var, "add.ignoreerrors") || 363 364 !strcmp(var, "add.ignore-errors")) { ··· 368 369 if (git_color_config(var, value, cb) < 0) 369 370 return -1; 370 371 371 - return git_default_config(var, value, cb); 372 + return git_default_config(var, value, ctx, cb); 372 373 } 373 374 374 375 static const char embedded_advice[] = N_(
+3 -2
builtin/blame.c
··· 694 694 return prefix_path(prefix, prefix ? strlen(prefix) : 0, path); 695 695 } 696 696 697 - static int git_blame_config(const char *var, const char *value, void *cb) 697 + static int git_blame_config(const char *var, const char *value, 698 + const struct config_context *ctx, void *cb) 698 699 { 699 700 if (!strcmp(var, "blame.showroot")) { 700 701 show_root = git_config_bool(var, value); ··· 767 768 if (userdiff_config(var, value) < 0) 768 769 return -1; 769 770 770 - return git_default_config(var, value, cb); 771 + return git_default_config(var, value, ctx, cb); 771 772 } 772 773 773 774 static int blame_copy_callback(const struct option *option, const char *arg, int unset)
+3 -2
builtin/branch.c
··· 83 83 84 84 define_list_config_array(color_branch_slots); 85 85 86 - static int git_branch_config(const char *var, const char *value, void *cb) 86 + static int git_branch_config(const char *var, const char *value, 87 + const struct config_context *ctx, void *cb) 87 88 { 88 89 const char *slot_name; 89 90 ··· 120 121 if (git_color_config(var, value, cb) < 0) 121 122 return -1; 122 123 123 - return git_default_config(var, value, cb); 124 + return git_default_config(var, value, ctx, cb); 124 125 } 125 126 126 127 static const char *branch_get_color(enum color_branch ix)
+3 -2
builtin/cat-file.c
··· 873 873 return retval; 874 874 } 875 875 876 - static int git_cat_file_config(const char *var, const char *value, void *cb) 876 + static int git_cat_file_config(const char *var, const char *value, 877 + const struct config_context *ctx, void *cb) 877 878 { 878 879 if (userdiff_config(var, value) < 0) 879 880 return -1; 880 881 881 - return git_default_config(var, value, cb); 882 + return git_default_config(var, value, ctx, cb); 882 883 } 883 884 884 885 static int batch_option_callback(const struct option *opt,
+9 -3
builtin/checkout.c
··· 1186 1186 return ret || writeout_error; 1187 1187 } 1188 1188 1189 - static int git_checkout_config(const char *var, const char *value, void *cb) 1189 + static int git_checkout_config(const char *var, const char *value, 1190 + const struct config_context *ctx, void *cb) 1190 1191 { 1191 1192 struct checkout_opts *opts = cb; 1192 1193 ··· 1202 1203 if (starts_with(var, "submodule.")) 1203 1204 return git_default_submodule_config(var, value, NULL); 1204 1205 1205 - return git_xmerge_config(var, value, NULL); 1206 + return git_xmerge_config(var, value, ctx, NULL); 1206 1207 } 1207 1208 1208 1209 static void setup_new_branch_info_and_source_tree( ··· 1689 1690 } 1690 1691 1691 1692 if (opts->conflict_style) { 1693 + struct key_value_info kvi = KVI_INIT; 1694 + struct config_context ctx = { 1695 + .kvi = &kvi, 1696 + }; 1692 1697 opts->merge = 1; /* implied */ 1693 - git_xmerge_config("merge.conflictstyle", opts->conflict_style, NULL); 1698 + git_xmerge_config("merge.conflictstyle", opts->conflict_style, 1699 + &ctx, NULL); 1694 1700 } 1695 1701 if (opts->force) { 1696 1702 opts->discard_changes = 1;
+3 -2
builtin/clean.c
··· 103 103 104 104 define_list_config_array(color_interactive_slots); 105 105 106 - static int git_clean_config(const char *var, const char *value, void *cb) 106 + static int git_clean_config(const char *var, const char *value, 107 + const struct config_context *ctx, void *cb) 107 108 { 108 109 const char *slot_name; 109 110 ··· 133 134 if (git_color_config(var, value, cb) < 0) 134 135 return -1; 135 136 136 - return git_default_config(var, value, cb); 137 + return git_default_config(var, value, ctx, cb); 137 138 } 138 139 139 140 static const char *clean_get_color(enum color_clean ix)
+7 -4
builtin/clone.c
··· 790 790 return err; 791 791 } 792 792 793 - static int git_clone_config(const char *k, const char *v, void *cb) 793 + static int git_clone_config(const char *k, const char *v, 794 + const struct config_context *ctx, void *cb) 794 795 { 795 796 if (!strcmp(k, "clone.defaultremotename")) { 796 797 free(remote_name); ··· 801 802 if (!strcmp(k, "clone.filtersubmodules")) 802 803 config_filter_submodules = git_config_bool(k, v); 803 804 804 - return git_default_config(k, v, cb); 805 + return git_default_config(k, v, ctx, cb); 805 806 } 806 807 807 - static int write_one_config(const char *key, const char *value, void *data) 808 + static int write_one_config(const char *key, const char *value, 809 + const struct config_context *ctx, 810 + void *data) 808 811 { 809 812 /* 810 813 * give git_clone_config a chance to write config values back to the 811 814 * environment, since git_config_set_multivar_gently only deals with 812 815 * config-file writes 813 816 */ 814 - int apply_failed = git_clone_config(key, value, data); 817 + int apply_failed = git_clone_config(key, value, ctx, data); 815 818 if (apply_failed) 816 819 return apply_failed; 817 820
+2 -1
builtin/column.c
··· 13 13 }; 14 14 static unsigned int colopts; 15 15 16 - static int column_config(const char *var, const char *value, void *cb) 16 + static int column_config(const char *var, const char *value, 17 + const struct config_context *ctx UNUSED, void *cb) 17 18 { 18 19 return git_column_config(var, value, cb, &colopts); 19 20 }
+1
builtin/commit-graph.c
··· 186 186 } 187 187 188 188 static int git_commit_graph_write_config(const char *var, const char *value, 189 + const struct config_context *ctx UNUSED, 189 190 void *cb UNUSED) 190 191 { 191 192 if (!strcmp(var, "commitgraph.maxnewfilters"))
+6 -4
builtin/commit.c
··· 1405 1405 return LOOKUP_CONFIG(color_status_slots, slot); 1406 1406 } 1407 1407 1408 - static int git_status_config(const char *k, const char *v, void *cb) 1408 + static int git_status_config(const char *k, const char *v, 1409 + const struct config_context *ctx, void *cb) 1409 1410 { 1410 1411 struct wt_status *s = cb; 1411 1412 const char *slot_name; ··· 1490 1491 s->detect_rename = git_config_rename(k, v); 1491 1492 return 0; 1492 1493 } 1493 - return git_diff_ui_config(k, v, NULL); 1494 + return git_diff_ui_config(k, v, ctx, NULL); 1494 1495 } 1495 1496 1496 1497 int cmd_status(int argc, const char **argv, const char *prefix) ··· 1605 1606 return 0; 1606 1607 } 1607 1608 1608 - static int git_commit_config(const char *k, const char *v, void *cb) 1609 + static int git_commit_config(const char *k, const char *v, 1610 + const struct config_context *ctx, void *cb) 1609 1611 { 1610 1612 struct wt_status *s = cb; 1611 1613 ··· 1627 1629 return 0; 1628 1630 } 1629 1631 1630 - return git_status_config(k, v, s); 1632 + return git_status_config(k, v, ctx, s); 1631 1633 } 1632 1634 1633 1635 int cmd_commit(int argc, const char **argv, const char *prefix)
+8 -2
builtin/config.c
··· 217 217 } 218 218 219 219 static int show_all_config(const char *key_, const char *value_, 220 + const struct config_context *ctx UNUSED, 220 221 void *cb UNUSED) 221 222 { 222 223 if (show_origin || show_scope) { ··· 301 302 return 0; 302 303 } 303 304 304 - static int collect_config(const char *key_, const char *value_, void *cb) 305 + static int collect_config(const char *key_, const char *value_, 306 + const struct config_context *ctx UNUSED, void *cb) 305 307 { 306 308 struct strbuf_list *values = cb; 307 309 ··· 470 472 static char parsed_color[COLOR_MAXLEN]; 471 473 472 474 static int git_get_color_config(const char *var, const char *value, 475 + const struct config_context *ctx UNUSED, 473 476 void *cb UNUSED) 474 477 { 475 478 if (!strcmp(var, get_color_slot)) { ··· 503 506 static int get_diff_color_found; 504 507 static int get_color_ui_found; 505 508 static int git_get_colorbool_config(const char *var, const char *value, 509 + const struct config_context *ctx UNUSED, 506 510 void *data UNUSED) 507 511 { 508 512 if (!strcmp(var, get_colorbool_slot)) ··· 561 565 struct strbuf value; 562 566 }; 563 567 564 - static int urlmatch_collect_fn(const char *var, const char *value, void *cb) 568 + static int urlmatch_collect_fn(const char *var, const char *value, 569 + const struct config_context *ctx UNUSED, 570 + void *cb) 565 571 { 566 572 struct string_list *values = cb; 567 573 struct string_list_item *item = string_list_insert(values, var);
+3 -2
builtin/difftool.c
··· 40 40 NULL 41 41 }; 42 42 43 - static int difftool_config(const char *var, const char *value, void *cb) 43 + static int difftool_config(const char *var, const char *value, 44 + const struct config_context *ctx, void *cb) 44 45 { 45 46 if (!strcmp(var, "difftool.trustexitcode")) { 46 47 trust_exit_code = git_config_bool(var, value); 47 48 return 0; 48 49 } 49 50 50 - return git_default_config(var, value, cb); 51 + return git_default_config(var, value, ctx, cb); 51 52 } 52 53 53 54 static int print_tool_help(void)
+6 -3
builtin/fetch.c
··· 110 110 int submodule_fetch_jobs; 111 111 }; 112 112 113 - static int git_fetch_config(const char *k, const char *v, void *cb) 113 + static int git_fetch_config(const char *k, const char *v, 114 + const struct config_context *ctx, void *cb) 114 115 { 115 116 struct fetch_config *fetch_config = cb; 116 117 ··· 164 165 "fetch.output", v); 165 166 } 166 167 167 - return git_default_config(k, v, cb); 168 + return git_default_config(k, v, ctx, cb); 168 169 } 169 170 170 171 static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) ··· 1799 1800 struct string_list *list; 1800 1801 }; 1801 1802 1802 - static int get_remote_group(const char *key, const char *value, void *priv) 1803 + static int get_remote_group(const char *key, const char *value, 1804 + const struct config_context *ctx UNUSED, 1805 + void *priv) 1803 1806 { 1804 1807 struct remote_group_data *g = priv; 1805 1808
+3 -2
builtin/fsmonitor--daemon.c
··· 37 37 #define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup" 38 38 static int fsmonitor__announce_startup = 0; 39 39 40 - static int fsmonitor_config(const char *var, const char *value, void *cb) 40 + static int fsmonitor_config(const char *var, const char *value, 41 + const struct config_context *ctx, void *cb) 41 42 { 42 43 if (!strcmp(var, FSMONITOR__IPC_THREADS)) { 43 44 int i = git_config_int(var, value); ··· 67 68 return 0; 68 69 } 69 70 70 - return git_default_config(var, value, cb); 71 + return git_default_config(var, value, ctx, cb); 71 72 } 72 73 73 74 /*
+4 -3
builtin/grep.c
··· 290 290 return hit; 291 291 } 292 292 293 - static int grep_cmd_config(const char *var, const char *value, void *cb) 293 + static int grep_cmd_config(const char *var, const char *value, 294 + const struct config_context *ctx, void *cb) 294 295 { 295 - int st = grep_config(var, value, cb); 296 + int st = grep_config(var, value, ctx, cb); 296 297 297 298 if (git_color_config(var, value, cb) < 0) 298 299 st = -1; 299 - else if (git_default_config(var, value, cb) < 0) 300 + else if (git_default_config(var, value, ctx, cb) < 0) 300 301 st = -1; 301 302 302 303 if (!strcmp(var, "grep.threads")) {
+3 -2
builtin/help.c
··· 398 398 return 0; 399 399 } 400 400 401 - static int git_help_config(const char *var, const char *value, void *cb) 401 + static int git_help_config(const char *var, const char *value, 402 + const struct config_context *ctx, void *cb) 402 403 { 403 404 if (!strcmp(var, "help.format")) { 404 405 if (!value) ··· 421 422 if (starts_with(var, "man.")) 422 423 return add_man_viewer_info(var, value); 423 424 424 - return git_default_config(var, value, cb); 425 + return git_default_config(var, value, ctx, cb); 425 426 } 426 427 427 428 static struct cmdnames main_cmds, other_cmds;
+3 -2
builtin/index-pack.c
··· 1581 1581 strbuf_release(&pack_name); 1582 1582 } 1583 1583 1584 - static int git_index_pack_config(const char *k, const char *v, void *cb) 1584 + static int git_index_pack_config(const char *k, const char *v, 1585 + const struct config_context *ctx, void *cb) 1585 1586 { 1586 1587 struct pack_idx_option *opts = cb; 1587 1588 ··· 1608 1609 else 1609 1610 opts->flags &= ~WRITE_REV; 1610 1611 } 1611 - return git_default_config(k, v, cb); 1612 + return git_default_config(k, v, ctx, cb); 1612 1613 } 1613 1614 1614 1615 static int cmp_uint32(const void *a_, const void *b_)
+6 -4
builtin/log.c
··· 564 564 return retval; 565 565 } 566 566 567 - static int git_log_config(const char *var, const char *value, void *cb) 567 + static int git_log_config(const char *var, const char *value, 568 + const struct config_context *ctx, void *cb) 568 569 { 569 570 const char *slot_name; 570 571 ··· 613 614 return 0; 614 615 } 615 616 616 - return git_diff_ui_config(var, value, cb); 617 + return git_diff_ui_config(var, value, ctx, cb); 617 618 } 618 619 619 620 int cmd_whatchanged(int argc, const char **argv, const char *prefix) ··· 979 980 die(_("%s: invalid cover from description mode"), arg); 980 981 } 981 982 982 - static int git_format_config(const char *var, const char *value, void *cb) 983 + static int git_format_config(const char *var, const char *value, 984 + const struct config_context *ctx, void *cb) 983 985 { 984 986 if (!strcmp(var, "format.headers")) { 985 987 if (!value) ··· 1108 1110 if (!strcmp(var, "diff.noprefix")) 1109 1111 return 0; 1110 1112 1111 - return git_log_config(var, value, cb); 1113 + return git_log_config(var, value, ctx, cb); 1112 1114 } 1113 1115 1114 1116 static const char *output_directory = NULL;
+4 -3
builtin/merge.c
··· 623 623 free(argv); 624 624 } 625 625 626 - static int git_merge_config(const char *k, const char *v, void *cb) 626 + static int git_merge_config(const char *k, const char *v, 627 + const struct config_context *ctx, void *cb) 627 628 { 628 629 int status; 629 630 const char *str; ··· 668 669 return 0; 669 670 } 670 671 671 - status = fmt_merge_msg_config(k, v, cb); 672 + status = fmt_merge_msg_config(k, v, ctx, cb); 672 673 if (status) 673 674 return status; 674 - return git_diff_ui_config(k, v, cb); 675 + return git_diff_ui_config(k, v, ctx, cb); 675 676 } 676 677 677 678 static int read_tree_trivial(struct object_id *common, struct object_id *head,
+1
builtin/multi-pack-index.c
··· 82 82 } 83 83 84 84 static int git_multi_pack_index_write_config(const char *var, const char *value, 85 + const struct config_context *ctx UNUSED, 85 86 void *cb UNUSED) 86 87 { 87 88 if (!strcmp(var, "pack.writebitmaphashcache")) {
+3 -2
builtin/pack-objects.c
··· 3135 3135 free(delta_list); 3136 3136 } 3137 3137 3138 - static int git_pack_config(const char *k, const char *v, void *cb) 3138 + static int git_pack_config(const char *k, const char *v, 3139 + const struct config_context *ctx, void *cb) 3139 3140 { 3140 3141 if (!strcmp(k, "pack.window")) { 3141 3142 window = git_config_int(k, v); ··· 3227 3228 ex->uri = xstrdup(pack_end + 1); 3228 3229 oidmap_put(&configured_exclusions, ex); 3229 3230 } 3230 - return git_default_config(k, v, cb); 3231 + return git_default_config(k, v, ctx, cb); 3231 3232 } 3232 3233 3233 3234 /* Counters for trace2 output when in --stdin-packs mode. */
+3 -2
builtin/patch-id.c
··· 196 196 int verbatim; 197 197 }; 198 198 199 - static int git_patch_id_config(const char *var, const char *value, void *cb) 199 + static int git_patch_id_config(const char *var, const char *value, 200 + const struct config_context *ctx, void *cb) 200 201 { 201 202 struct patch_id_opts *opts = cb; 202 203 ··· 209 210 return 0; 210 211 } 211 212 212 - return git_default_config(var, value, cb); 213 + return git_default_config(var, value, ctx, cb); 213 214 } 214 215 215 216 int cmd_patch_id(int argc, const char **argv, const char *prefix)
+3 -2
builtin/pull.c
··· 361 361 /** 362 362 * Read config variables. 363 363 */ 364 - static int git_pull_config(const char *var, const char *value, void *cb) 364 + static int git_pull_config(const char *var, const char *value, 365 + const struct config_context *ctx, void *cb) 365 366 { 366 367 if (!strcmp(var, "rebase.autostash")) { 367 368 config_autostash = git_config_bool(var, value); ··· 374 375 check_trust_level = 0; 375 376 } 376 377 377 - return git_default_config(var, value, cb); 378 + return git_default_config(var, value, ctx, cb); 378 379 } 379 380 380 381 /**
+3 -2
builtin/push.c
··· 510 510 } 511 511 512 512 513 - static int git_push_config(const char *k, const char *v, void *cb) 513 + static int git_push_config(const char *k, const char *v, 514 + const struct config_context *ctx, void *cb) 514 515 { 515 516 const char *slot_name; 516 517 int *flags = cb; ··· 577 578 return 0; 578 579 } 579 580 580 - return git_default_config(k, v, NULL); 581 + return git_default_config(k, v, ctx, NULL); 581 582 } 582 583 583 584 int cmd_push(int argc, const char **argv, const char *prefix)
+3 -2
builtin/read-tree.c
··· 102 102 return 0; 103 103 } 104 104 105 - static int git_read_tree_config(const char *var, const char *value, void *cb) 105 + static int git_read_tree_config(const char *var, const char *value, 106 + const struct config_context *ctx, void *cb) 106 107 { 107 108 if (!strcmp(var, "submodule.recurse")) 108 109 return git_default_submodule_config(var, value, cb); 109 110 110 - return git_default_config(var, value, cb); 111 + return git_default_config(var, value, ctx, cb); 111 112 } 112 113 113 114 int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
+3 -2
builtin/rebase.c
··· 772 772 die(_("Unknown rebase-merges mode: %s"), value); 773 773 } 774 774 775 - static int rebase_config(const char *var, const char *value, void *data) 775 + static int rebase_config(const char *var, const char *value, 776 + const struct config_context *ctx, void *data) 776 777 { 777 778 struct rebase_options *opts = data; 778 779 ··· 831 832 return git_config_string(&opts->default_backend, var, value); 832 833 } 833 834 834 - return git_default_config(var, value, data); 835 + return git_default_config(var, value, ctx, data); 835 836 } 836 837 837 838 static int checkout_up_to_date(struct rebase_options *options)
+3 -2
builtin/receive-pack.c
··· 139 139 return DENY_IGNORE; 140 140 } 141 141 142 - static int receive_pack_config(const char *var, const char *value, void *cb) 142 + static int receive_pack_config(const char *var, const char *value, 143 + const struct config_context *ctx, void *cb) 143 144 { 144 145 int status = parse_hide_refs_config(var, value, "receive", &hidden_refs); 145 146 ··· 266 267 return 0; 267 268 } 268 269 269 - return git_default_config(var, value, cb); 270 + return git_default_config(var, value, ctx, cb); 270 271 } 271 272 272 273 static void show_ref(const char *path, const struct object_id *oid)
+4 -3
builtin/reflog.c
··· 108 108 #define EXPIRE_TOTAL 01 109 109 #define EXPIRE_UNREACH 02 110 110 111 - static int reflog_expire_config(const char *var, const char *value, void *cb) 111 + static int reflog_expire_config(const char *var, const char *value, 112 + const struct config_context *ctx, void *cb) 112 113 { 113 114 const char *pattern, *key; 114 115 size_t pattern_len; ··· 117 118 struct reflog_expire_cfg *ent; 118 119 119 120 if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) 120 - return git_default_config(var, value, cb); 121 + return git_default_config(var, value, ctx, cb); 121 122 122 123 if (!strcmp(key, "reflogexpire")) { 123 124 slot = EXPIRE_TOTAL; ··· 128 129 if (git_config_expiry_date(&expire, var, value)) 129 130 return -1; 130 131 } else 131 - return git_default_config(var, value, cb); 132 + return git_default_config(var, value, ctx, cb); 132 133 133 134 if (!pattern) { 134 135 switch (slot) {
+5 -2
builtin/remote.c
··· 268 268 #define abbrev_branch(name) abbrev_ref((name), "refs/heads/") 269 269 270 270 static int config_read_branches(const char *key, const char *value, 271 + const struct config_context *ctx UNUSED, 271 272 void *data UNUSED) 272 273 { 273 274 const char *orig_key = key; ··· 645 646 }; 646 647 647 648 static int config_read_push_default(const char *key, const char *value, 648 - void *cb) 649 + const struct config_context *ctx UNUSED, void *cb) 649 650 { 650 651 struct push_default_info* info = cb; 651 652 if (strcmp(key, "remote.pushdefault") || ··· 1494 1495 return result; 1495 1496 } 1496 1497 1497 - static int get_remote_default(const char *key, const char *value UNUSED, void *priv) 1498 + static int get_remote_default(const char *key, const char *value UNUSED, 1499 + const struct config_context *ctx UNUSED, 1500 + void *priv) 1498 1501 { 1499 1502 if (strcmp(key, "remotes.default") == 0) { 1500 1503 int *found = priv;
+3 -2
builtin/repack.c
··· 59 59 int local; 60 60 }; 61 61 62 - static int repack_config(const char *var, const char *value, void *cb) 62 + static int repack_config(const char *var, const char *value, 63 + const struct config_context *ctx, void *cb) 63 64 { 64 65 struct pack_objects_args *cruft_po_args = cb; 65 66 if (!strcmp(var, "repack.usedeltabaseoffset")) { ··· 91 92 return git_config_string(&cruft_po_args->depth, var, value); 92 93 if (!strcmp(var, "repack.cruftthreads")) 93 94 return git_config_string(&cruft_po_args->threads, var, value); 94 - return git_default_config(var, value, cb); 95 + return git_default_config(var, value, ctx, cb); 95 96 } 96 97 97 98 /*
+3 -2
builtin/reset.c
··· 312 312 return update_ref_status; 313 313 } 314 314 315 - static int git_reset_config(const char *var, const char *value, void *cb) 315 + static int git_reset_config(const char *var, const char *value, 316 + const struct config_context *ctx, void *cb) 316 317 { 317 318 if (!strcmp(var, "submodule.recurse")) 318 319 return git_default_submodule_config(var, value, cb); 319 320 320 - return git_default_config(var, value, cb); 321 + return git_default_config(var, value, ctx, cb); 321 322 } 322 323 323 324 int cmd_reset(int argc, const char **argv, const char *prefix)
+3 -2
builtin/send-pack.c
··· 131 131 strbuf_release(&buf); 132 132 } 133 133 134 - static int send_pack_config(const char *k, const char *v, void *cb) 134 + static int send_pack_config(const char *k, const char *v, 135 + const struct config_context *ctx, void *cb) 135 136 { 136 137 if (!strcmp(k, "push.gpgsign")) { 137 138 const char *value; ··· 151 152 } 152 153 } 153 154 } 154 - return git_default_config(k, v, cb); 155 + return git_default_config(k, v, ctx, cb); 155 156 } 156 157 157 158 int cmd_send_pack(int argc, const char **argv, const char *prefix)
+3 -2
builtin/show-branch.c
··· 559 559 die("bad sha1 reference %s", av); 560 560 } 561 561 562 - static int git_show_branch_config(const char *var, const char *value, void *cb) 562 + static int git_show_branch_config(const char *var, const char *value, 563 + const struct config_context *ctx, void *cb) 563 564 { 564 565 if (!strcmp(var, "showbranch.default")) { 565 566 if (!value) ··· 582 583 if (git_color_config(var, value, cb) < 0) 583 584 return -1; 584 585 585 - return git_default_config(var, value, cb); 586 + return git_default_config(var, value, ctx, cb); 586 587 } 587 588 588 589 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
+3 -2
builtin/stash.c
··· 837 837 static int show_patch; 838 838 static int show_include_untracked; 839 839 840 - static int git_stash_config(const char *var, const char *value, void *cb) 840 + static int git_stash_config(const char *var, const char *value, 841 + const struct config_context *ctx, void *cb) 841 842 { 842 843 if (!strcmp(var, "stash.showstat")) { 843 844 show_stat = git_config_bool(var, value); ··· 851 852 show_include_untracked = git_config_bool(var, value); 852 853 return 0; 853 854 } 854 - return git_diff_basic_config(var, value, cb); 855 + return git_diff_basic_config(var, value, ctx, cb); 855 856 } 856 857 857 858 static void diff_include_untracked(const struct stash_info *info, struct diff_options *diff_opt)
+1
builtin/submodule--helper.c
··· 2192 2192 } 2193 2193 2194 2194 static int git_update_clone_config(const char *var, const char *value, 2195 + const struct config_context *ctx UNUSED, 2195 2196 void *cb) 2196 2197 { 2197 2198 int *max_jobs = cb;
+3 -2
builtin/tag.c
··· 188 188 "Lines starting with '%c' will be kept; you may remove them" 189 189 " yourself if you want to.\n"); 190 190 191 - static int git_tag_config(const char *var, const char *value, void *cb) 191 + static int git_tag_config(const char *var, const char *value, 192 + const struct config_context *ctx, void *cb) 192 193 { 193 194 if (!strcmp(var, "tag.gpgsign")) { 194 195 config_sign_tag = git_config_bool(var, value); ··· 213 214 if (git_color_config(var, value, cb) < 0) 214 215 return -1; 215 216 216 - return git_default_config(var, value, cb); 217 + return git_default_config(var, value, ctx, cb); 217 218 } 218 219 219 220 static void write_tag_body(int fd, const struct object_id *oid)
+3 -2
builtin/var.c
··· 71 71 return NULL; 72 72 } 73 73 74 - static int show_config(const char *var, const char *value, void *cb) 74 + static int show_config(const char *var, const char *value, 75 + const struct config_context *ctx, void *cb) 75 76 { 76 77 if (value) 77 78 printf("%s=%s\n", var, value); 78 79 else 79 80 printf("%s\n", var); 80 - return git_default_config(var, value, cb); 81 + return git_default_config(var, value, ctx, cb); 81 82 } 82 83 83 84 int cmd_var(int argc, const char **argv, const char *prefix UNUSED)
+3 -2
builtin/worktree.c
··· 128 128 static int guess_remote; 129 129 static timestamp_t expire; 130 130 131 - static int git_worktree_config(const char *var, const char *value, void *cb) 131 + static int git_worktree_config(const char *var, const char *value, 132 + const struct config_context *ctx, void *cb) 132 133 { 133 134 if (!strcmp(var, "worktree.guessremote")) { 134 135 guess_remote = git_config_bool(var, value); 135 136 return 0; 136 137 } 137 138 138 - return git_default_config(var, value, cb); 139 + return git_default_config(var, value, ctx, cb); 139 140 } 140 141 141 142 static int delete_git_dir(const char *id)
+6 -2
bundle-uri.c
··· 224 224 return 0; 225 225 } 226 226 227 - static int config_to_bundle_list(const char *key, const char *value, void *data) 227 + static int config_to_bundle_list(const char *key, const char *value, 228 + const struct config_context *ctx UNUSED, 229 + void *data) 228 230 { 229 231 struct bundle_list *list = data; 230 232 return bundle_list_update(key, value, list); ··· 871 873 return advertise_bundle_uri; 872 874 } 873 875 874 - static int config_to_packet_line(const char *key, const char *value, void *data) 876 + static int config_to_packet_line(const char *key, const char *value, 877 + const struct config_context *ctx UNUSED, 878 + void *data) 875 879 { 876 880 struct packet_reader *writer = data; 877 881
+2 -1
compat/mingw.c
··· 244 244 static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; 245 245 static char *unset_environment_variables; 246 246 247 - int mingw_core_config(const char *var, const char *value, void *cb) 247 + int mingw_core_config(const char *var, const char *value, 248 + const struct config_context *ctx, void *cb) 248 249 { 249 250 if (!strcmp(var, "core.hidedotfiles")) { 250 251 if (value && !strcasecmp(value, "dotgitonly"))
+3 -1
compat/mingw.h
··· 11 11 #undef _POSIX_THREAD_SAFE_FUNCTIONS 12 12 #endif 13 13 14 - int mingw_core_config(const char *var, const char *value, void *cb); 14 + struct config_context; 15 + int mingw_core_config(const char *var, const char *value, 16 + const struct config_context *ctx, void *cb); 15 17 #define platform_core_config mingw_core_config 16 18 17 19 /*
+24 -14
config.c
··· 209 209 }; 210 210 #define CONFIG_INCLUDE_INIT { 0 } 211 211 212 - static int git_config_include(const char *var, const char *value, void *data); 212 + static int git_config_include(const char *var, const char *value, 213 + const struct config_context *ctx, void *data); 213 214 214 215 #define MAX_INCLUDE_DEPTH 10 215 216 static const char include_depth_advice[] = N_( ··· 388 389 return ret; 389 390 } 390 391 391 - static int add_remote_url(const char *var, const char *value, void *data) 392 + static int add_remote_url(const char *var, const char *value, 393 + const struct config_context *ctx UNUSED, void *data) 392 394 { 393 395 struct string_list *remote_urls = data; 394 396 const char *remote_name; ··· 423 425 } 424 426 425 427 static int forbid_remote_url(const char *var, const char *value UNUSED, 428 + const struct config_context *ctx UNUSED, 426 429 void *data UNUSED) 427 430 { 428 431 const char *remote_name; ··· 486 489 return 0; 487 490 } 488 491 489 - static int git_config_include(const char *var, const char *value, void *data) 492 + static int git_config_include(const char *var, const char *value, 493 + const struct config_context *ctx, 494 + void *data) 490 495 { 491 496 struct config_include_data *inc = data; 492 497 struct config_source *cs = inc->config_reader->source; ··· 498 503 * Pass along all values, including "include" directives; this makes it 499 504 * possible to query information on the includes themselves. 500 505 */ 501 - ret = inc->fn(var, value, inc->data); 506 + ret = inc->fn(var, value, NULL, inc->data); 502 507 if (ret < 0) 503 508 return ret; 504 509 ··· 680 685 if (git_config_parse_key(key, &canonical_name, NULL)) 681 686 return -1; 682 687 683 - ret = (fn(canonical_name, value, data) < 0) ? -1 : 0; 688 + ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0; 684 689 free(canonical_name); 685 690 return ret; 686 691 } ··· 968 973 * accurate line number in error messages. 969 974 */ 970 975 cs->linenr--; 971 - ret = fn(name->buf, value, data); 976 + ret = fn(name->buf, value, NULL, data); 972 977 if (ret >= 0) 973 978 cs->linenr++; 974 979 return ret; ··· 1562 1567 return 0; 1563 1568 } 1564 1569 1565 - static int git_default_core_config(const char *var, const char *value, void *cb) 1570 + static int git_default_core_config(const char *var, const char *value, 1571 + const struct config_context *ctx, void *cb) 1566 1572 { 1567 1573 /* This needs a better name */ 1568 1574 if (!strcmp(var, "core.filemode")) { ··· 1842 1848 } 1843 1849 1844 1850 /* Add other config variables here and to Documentation/config.txt. */ 1845 - return platform_core_config(var, value, cb); 1851 + return platform_core_config(var, value, ctx, cb); 1846 1852 } 1847 1853 1848 1854 static int git_default_sparse_config(const char *var, const char *value) ··· 1944 1950 return 0; 1945 1951 } 1946 1952 1947 - int git_default_config(const char *var, const char *value, void *cb) 1953 + int git_default_config(const char *var, const char *value, 1954 + const struct config_context *ctx, void *cb) 1948 1955 { 1949 1956 if (starts_with(var, "core.")) 1950 - return git_default_core_config(var, value, cb); 1957 + return git_default_core_config(var, value, ctx, cb); 1951 1958 1952 1959 if (starts_with(var, "user.") || 1953 1960 starts_with(var, "author.") || 1954 1961 starts_with(var, "committer.")) 1955 - return git_ident_config(var, value, cb); 1962 + return git_ident_config(var, value, ctx, cb); 1956 1963 1957 1964 if (starts_with(var, "i18n.")) 1958 1965 return git_default_i18n_config(var, value); ··· 2318 2325 2319 2326 config_reader_set_kvi(reader, values->items[value_index].util); 2320 2327 2321 - if (fn(entry->key, values->items[value_index].string, data) < 0) 2328 + if (fn(entry->key, values->items[value_index].string, NULL, data) < 0) 2322 2329 git_die_config_linenr(entry->key, 2323 2330 reader->config_kvi->filename, 2324 2331 reader->config_kvi->linenr); ··· 2496 2503 }; 2497 2504 #define CONFIGSET_ADD_INIT { 0 } 2498 2505 2499 - static int config_set_callback(const char *key, const char *value, void *cb) 2506 + static int config_set_callback(const char *key, const char *value, 2507 + const struct config_context *ctx UNUSED, 2508 + void *cb) 2500 2509 { 2501 2510 struct configset_add_data *data = cb; 2502 2511 configset_add_value(data->config_reader, data->config_set, key, value); ··· 3106 3115 return 0; 3107 3116 } 3108 3117 3109 - static int store_aux(const char *key, const char *value, void *cb) 3118 + static int store_aux(const char *key, const char *value, 3119 + const struct config_context *ctx UNUSED, void *cb) 3110 3120 { 3111 3121 struct config_store_data *store = cb; 3112 3122
+31 -10
config.h
··· 110 110 } error_action; 111 111 }; 112 112 113 + /* Config source metadata for a given config key-value pair */ 114 + struct key_value_info { 115 + const char *filename; 116 + int linenr; 117 + enum config_origin_type origin_type; 118 + enum config_scope scope; 119 + }; 120 + #define KVI_INIT { \ 121 + .filename = NULL, \ 122 + .linenr = -1, \ 123 + .origin_type = CONFIG_ORIGIN_UNKNOWN, \ 124 + .scope = CONFIG_SCOPE_UNKNOWN, \ 125 + } 126 + 127 + /* Captures additional information that a config callback can use. */ 128 + struct config_context { 129 + /* Config source metadata for key and value. */ 130 + const struct key_value_info *kvi; 131 + }; 132 + #define CONFIG_CONTEXT_INIT { 0 } 133 + 113 134 /** 114 - * A config callback function takes three parameters: 135 + * A config callback function takes four parameters: 115 136 * 116 137 * - the name of the parsed variable. This is in canonical "flat" form: the 117 138 * section, subsection, and variable segments will be separated by dots, ··· 122 143 * value specified, the value will be NULL (typically this means it 123 144 * should be interpreted as boolean true). 124 145 * 146 + * - the 'config context', that is, additional information about the config 147 + * iteration operation provided by the config machinery. For example, this 148 + * includes information about the config source being parsed (e.g. the 149 + * filename). 150 + * 125 151 * - a void pointer passed in by the caller of the config API; this can 126 152 * contain callback-specific data 127 153 * 128 154 * A config callback should return 0 for success, or -1 if the variable 129 155 * could not be parsed properly. 130 156 */ 131 - typedef int (*config_fn_t)(const char *, const char *, void *); 157 + typedef int (*config_fn_t)(const char *, const char *, 158 + const struct config_context *, void *); 132 159 133 - int git_default_config(const char *, const char *, void *); 160 + int git_default_config(const char *, const char *, 161 + const struct config_context *, void *); 134 162 135 163 /** 136 164 * Read a specific file in git-config format. ··· 666 694 667 695 /* parse either "this many days" integer, or "5.days.ago" approxidate */ 668 696 int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now); 669 - 670 - struct key_value_info { 671 - const char *filename; 672 - int linenr; 673 - enum config_origin_type origin_type; 674 - enum config_scope scope; 675 - }; 676 697 677 698 /** 678 699 * First prints the error message specified by the caller in `err` and then
+2 -2
connect.c
··· 964 964 static char *git_proxy_command; 965 965 966 966 static int git_proxy_command_options(const char *var, const char *value, 967 - void *cb) 967 + const struct config_context *ctx, void *cb) 968 968 { 969 969 if (!strcmp(var, "core.gitproxy")) { 970 970 const char *for_pos; ··· 1010 1010 return 0; 1011 1011 } 1012 1012 1013 - return git_default_config(var, value, cb); 1013 + return git_default_config(var, value, ctx, cb); 1014 1014 } 1015 1015 1016 1016 static int git_use_proxy(const char *host)
+144
contrib/coccinelle/config_fn_ctx.pending.cocci
··· 1 + @ get_fn @ 2 + identifier fn, R; 3 + @@ 4 + ( 5 + ( 6 + git_config_from_file 7 + | 8 + git_config_from_file_with_options 9 + | 10 + git_config_from_mem 11 + | 12 + git_config_from_blob_oid 13 + | 14 + read_early_config 15 + | 16 + read_very_early_config 17 + | 18 + config_with_options 19 + | 20 + git_config 21 + | 22 + git_protected_config 23 + | 24 + config_from_gitmodules 25 + ) 26 + (fn, ...) 27 + | 28 + repo_config(R, fn, ...) 29 + ) 30 + 31 + @ extends get_fn @ 32 + identifier C1, C2, D; 33 + @@ 34 + int fn(const char *C1, const char *C2, 35 + + const struct config_context *ctx, 36 + void *D); 37 + 38 + @ extends get_fn @ 39 + @@ 40 + int fn(const char *, const char *, 41 + + const struct config_context *, 42 + void *); 43 + 44 + @ extends get_fn @ 45 + // Don't change fns that look like callback fns but aren't 46 + identifier fn2 != tar_filter_config && != git_diff_heuristic_config && 47 + != git_default_submodule_config && != git_color_config && 48 + != bundle_list_update && != parse_object_filter_config; 49 + identifier C1, C2, D1, D2, S; 50 + attribute name UNUSED; 51 + @@ 52 + int fn(const char *C1, const char *C2, 53 + + const struct config_context *ctx, 54 + void *D1) { 55 + <+... 56 + ( 57 + fn2(C1, C2 58 + + , ctx 59 + , D2); 60 + | 61 + if(fn2(C1, C2 62 + + , ctx 63 + , D2) < 0) { ... } 64 + | 65 + return fn2(C1, C2 66 + + , ctx 67 + , D2); 68 + | 69 + S = fn2(C1, C2 70 + + , ctx 71 + , D2); 72 + ) 73 + ...+> 74 + } 75 + 76 + @ extends get_fn@ 77 + identifier C1, C2, D; 78 + attribute name UNUSED; 79 + @@ 80 + int fn(const char *C1, const char *C2, 81 + + const struct config_context *ctx UNUSED, 82 + void *D) {...} 83 + 84 + 85 + // The previous rules don't catch all callbacks, especially if they're defined 86 + // in a separate file from the git_config() call. Fix these manually. 87 + @@ 88 + identifier C1, C2, D; 89 + attribute name UNUSED; 90 + @@ 91 + int 92 + ( 93 + git_ident_config 94 + | 95 + urlmatch_collect_fn 96 + | 97 + write_one_config 98 + | 99 + forbid_remote_url 100 + | 101 + credential_config_callback 102 + ) 103 + (const char *C1, const char *C2, 104 + + const struct config_context *ctx UNUSED, 105 + void *D) {...} 106 + 107 + @@ 108 + identifier C1, C2, D, D2, S, fn2; 109 + @@ 110 + int 111 + ( 112 + http_options 113 + | 114 + git_status_config 115 + | 116 + git_commit_config 117 + | 118 + git_default_core_config 119 + | 120 + grep_config 121 + ) 122 + (const char *C1, const char *C2, 123 + + const struct config_context *ctx, 124 + void *D) { 125 + <+... 126 + ( 127 + fn2(C1, C2 128 + + , ctx 129 + , D2); 130 + | 131 + if(fn2(C1, C2 132 + + , ctx 133 + , D2) < 0) { ... } 134 + | 135 + return fn2(C1, C2 136 + + , ctx 137 + , D2); 138 + | 139 + S = fn2(C1, C2 140 + + , ctx 141 + , D2); 142 + ) 143 + ...+> 144 + }
+3 -1
convert.c
··· 1015 1015 return 0; 1016 1016 } 1017 1017 1018 - static int read_convert_config(const char *var, const char *value, void *cb UNUSED) 1018 + static int read_convert_config(const char *var, const char *value, 1019 + const struct config_context *ctx UNUSED, 1020 + void *cb UNUSED) 1019 1021 { 1020 1022 const char *key, *name; 1021 1023 size_t namelen;
+1
credential.c
··· 49 49 const char *url); 50 50 51 51 static int credential_config_callback(const char *var, const char *value, 52 + const struct config_context *ctx UNUSED, 52 53 void *data) 53 54 { 54 55 struct credential *c = data;
+3 -1
delta-islands.c
··· 341 341 kh_destroy_str(remote_islands); 342 342 } 343 343 344 - static int island_config_callback(const char *k, const char *v, void *cb) 344 + static int island_config_callback(const char *k, const char *v, 345 + const struct config_context *ctx UNUSED, 346 + void *cb) 345 347 { 346 348 struct island_load_data *ild = cb; 347 349
+6 -4
diff.c
··· 357 357 return ret; 358 358 } 359 359 360 - int git_diff_ui_config(const char *var, const char *value, void *cb) 360 + int git_diff_ui_config(const char *var, const char *value, 361 + const struct config_context *ctx, void *cb) 361 362 { 362 363 if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { 363 364 diff_use_color_default = git_config_colorbool(var, value); ··· 440 441 if (git_color_config(var, value, cb) < 0) 441 442 return -1; 442 443 443 - return git_diff_basic_config(var, value, cb); 444 + return git_diff_basic_config(var, value, ctx, cb); 444 445 } 445 446 446 - int git_diff_basic_config(const char *var, const char *value, void *cb) 447 + int git_diff_basic_config(const char *var, const char *value, 448 + const struct config_context *ctx, void *cb) 447 449 { 448 450 const char *name; 449 451 ··· 495 497 if (git_diff_heuristic_config(var, value, cb) < 0) 496 498 return -1; 497 499 498 - return git_default_config(var, value, cb); 500 + return git_default_config(var, value, ctx, cb); 499 501 } 500 502 501 503 static char *quote_two(const char *one, const char *two)
+5 -2
diff.h
··· 531 531 int parse_long_opt(const char *opt, const char **argv, 532 532 const char **optarg); 533 533 534 - int git_diff_basic_config(const char *var, const char *value, void *cb); 534 + struct config_context; 535 + int git_diff_basic_config(const char *var, const char *value, 536 + const struct config_context *ctx, void *cb); 535 537 int git_diff_heuristic_config(const char *var, const char *value, void *cb); 536 538 void init_diff_ui_defaults(void); 537 - int git_diff_ui_config(const char *var, const char *value, void *cb); 539 + int git_diff_ui_config(const char *var, const char *value, 540 + const struct config_context *ctx, void *cb); 538 541 void repo_diff_setup(struct repository *, struct diff_options *); 539 542 struct option *add_diff_options(const struct option *, struct diff_options *); 540 543 int diff_opt_parse(struct diff_options *, const char **, int, const char *);
+3 -2
fetch-pack.c
··· 1860 1860 return ref; 1861 1861 } 1862 1862 1863 - static int fetch_pack_config_cb(const char *var, const char *value, void *cb) 1863 + static int fetch_pack_config_cb(const char *var, const char *value, 1864 + const struct config_context *ctx, void *cb) 1864 1865 { 1865 1866 if (strcmp(var, "fetch.fsck.skiplist") == 0) { 1866 1867 const char *path; ··· 1882 1883 return 0; 1883 1884 } 1884 1885 1885 - return git_default_config(var, value, cb); 1886 + return git_default_config(var, value, ctx, cb); 1886 1887 } 1887 1888 1888 1889 static void fetch_pack_config(void)
+3 -2
fmt-merge-msg.c
··· 20 20 static int suppress_dest_pattern_seen; 21 21 static struct string_list suppress_dest_patterns = STRING_LIST_INIT_DUP; 22 22 23 - int fmt_merge_msg_config(const char *key, const char *value, void *cb) 23 + int fmt_merge_msg_config(const char *key, const char *value, 24 + const struct config_context *ctx, void *cb) 24 25 { 25 26 if (!strcmp(key, "merge.log") || !strcmp(key, "merge.summary")) { 26 27 int is_bool; ··· 40 41 string_list_append(&suppress_dest_patterns, value); 41 42 suppress_dest_pattern_seen = 1; 42 43 } else { 43 - return git_default_config(key, value, cb); 44 + return git_default_config(key, value, ctx, cb); 44 45 } 45 46 return 0; 46 47 }
+2 -1
fmt-merge-msg.h
··· 13 13 }; 14 14 15 15 extern int merge_log_config; 16 - int fmt_merge_msg_config(const char *key, const char *value, void *cb); 16 + int fmt_merge_msg_config(const char *key, const char *value, 17 + const struct config_context *ctx, void *cb); 17 18 int fmt_merge_msg(struct strbuf *in, struct strbuf *out, 18 19 struct fmt_merge_msg_opts *); 19 20
+6 -3
fsck.c
··· 1163 1163 int ret; 1164 1164 }; 1165 1165 1166 - static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata) 1166 + static int fsck_gitmodules_fn(const char *var, const char *value, 1167 + const struct config_context *ctx UNUSED, 1168 + void *vdata) 1167 1169 { 1168 1170 struct fsck_gitmodules_data *data = vdata; 1169 1171 const char *subsection, *key; ··· 1373 1375 return ret; 1374 1376 } 1375 1377 1376 - int git_fsck_config(const char *var, const char *value, void *cb) 1378 + int git_fsck_config(const char *var, const char *value, 1379 + const struct config_context *ctx, void *cb) 1377 1380 { 1378 1381 struct fsck_options *options = cb; 1379 1382 if (strcmp(var, "fsck.skiplist") == 0) { ··· 1394 1397 return 0; 1395 1398 } 1396 1399 1397 - return git_default_config(var, value, cb); 1400 + return git_default_config(var, value, ctx, cb); 1398 1401 } 1399 1402 1400 1403 /*
+3 -1
fsck.h
··· 233 233 const char *fsck_describe_object(struct fsck_options *options, 234 234 const struct object_id *oid); 235 235 236 + struct key_value_info; 236 237 /* 237 238 * git_config() callback for use by fsck-y tools that want to support 238 239 * fsck.<msg> fsck.skipList etc. 239 240 */ 240 - int git_fsck_config(const char *var, const char *value, void *cb); 241 + int git_fsck_config(const char *var, const char *value, 242 + const struct config_context *ctx, void *cb); 241 243 242 244 #endif
+2
git-compat-util.h
··· 440 440 #endif 441 441 442 442 #ifndef platform_core_config 443 + struct config_context; 443 444 static inline int noop_core_config(const char *var UNUSED, 444 445 const char *value UNUSED, 446 + const struct config_context *ctx UNUSED, 445 447 void *cb UNUSED) 446 448 { 447 449 return 0;
+5 -2
gpg-interface.c
··· 14 14 #include "alias.h" 15 15 #include "wrapper.h" 16 16 17 - static int git_gpg_config(const char *, const char *, void *); 17 + static int git_gpg_config(const char *, const char *, 18 + const struct config_context *, void *); 18 19 19 20 static void gpg_interface_lazy_init(void) 20 21 { ··· 720 721 configured_signing_key = xstrdup(key); 721 722 } 722 723 723 - static int git_gpg_config(const char *var, const char *value, void *cb UNUSED) 724 + static int git_gpg_config(const char *var, const char *value, 725 + const struct config_context *ctx UNUSED, 726 + void *cb UNUSED) 724 727 { 725 728 struct gpg_format *fmt = NULL; 726 729 char *fmtname = NULL;
+4 -3
grep.c
··· 56 56 * Read the configuration file once and store it in 57 57 * the grep_defaults template. 58 58 */ 59 - int grep_config(const char *var, const char *value, void *cb) 59 + int grep_config(const char *var, const char *value, 60 + const struct config_context *ctx, void *cb) 60 61 { 61 62 struct grep_opt *opt = cb; 62 63 const char *slot; ··· 91 92 if (!strcmp(var, "color.grep")) 92 93 opt->color = git_config_colorbool(var, value); 93 94 if (!strcmp(var, "color.grep.match")) { 94 - if (grep_config("color.grep.matchcontext", value, cb) < 0) 95 + if (grep_config("color.grep.matchcontext", value, ctx, cb) < 0) 95 96 return -1; 96 - if (grep_config("color.grep.matchselected", value, cb) < 0) 97 + if (grep_config("color.grep.matchselected", value, ctx, cb) < 0) 97 98 return -1; 98 99 } else if (skip_prefix(var, "color.grep.", &slot)) { 99 100 int i = LOOKUP_CONFIG(color_grep_slots, slot);
+3 -1
grep.h
··· 202 202 .output = std_output, \ 203 203 } 204 204 205 - int grep_config(const char *var, const char *value, void *); 205 + struct config_context; 206 + int grep_config(const char *var, const char *value, 207 + const struct config_context *ctx, void *data); 206 208 void grep_init(struct grep_opt *, struct repository *repo); 207 209 208 210 void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
+5 -2
help.c
··· 309 309 exclude_cmds(other_cmds, main_cmds); 310 310 } 311 311 312 - static int get_colopts(const char *var, const char *value, void *data) 312 + static int get_colopts(const char *var, const char *value, 313 + const struct config_context *ctx UNUSED, void *data) 313 314 { 314 315 unsigned int *colopts = data; 315 316 ··· 459 460 putchar('\n'); 460 461 } 461 462 462 - static int get_alias(const char *var, const char *value, void *data) 463 + static int get_alias(const char *var, const char *value, 464 + const struct config_context *ctx UNUSED, void *data) 463 465 { 464 466 struct string_list *list = data; 465 467 ··· 543 545 #define AUTOCORRECT_IMMEDIATELY (-1) 544 546 545 547 static int git_unknown_cmd_config(const char *var, const char *value, 548 + const struct config_context *ctx UNUSED, 546 549 void *cb UNUSED) 547 550 { 548 551 const char *p;
+3 -2
http.c
··· 363 363 } 364 364 } 365 365 366 - static int http_options(const char *var, const char *value, void *cb) 366 + static int http_options(const char *var, const char *value, 367 + const struct config_context *ctx, void *data) 367 368 { 368 369 if (!strcmp("http.version", var)) { 369 370 return git_config_string(&curl_http_version, var, value); ··· 534 535 } 535 536 536 537 /* Fall back on the default ones */ 537 - return git_default_config(var, value, cb); 538 + return git_default_config(var, value, ctx, data); 538 539 } 539 540 540 541 static int curl_empty_auth_enabled(void)
+3 -1
ident.c
··· 671 671 return 0; 672 672 } 673 673 674 - int git_ident_config(const char *var, const char *value, void *data UNUSED) 674 + int git_ident_config(const char *var, const char *value, 675 + const struct config_context *ctx UNUSED, 676 + void *data UNUSED) 675 677 { 676 678 if (!strcmp(var, "user.useconfigonly")) { 677 679 ident_use_config_only = git_config_bool(var, value);
+3 -1
ident.h
··· 62 62 int committer_ident_sufficiently_given(void); 63 63 int author_ident_sufficiently_given(void); 64 64 65 - int git_ident_config(const char *, const char *, void *); 65 + struct config_context; 66 + int git_ident_config(const char *, const char *, const struct config_context *, 67 + void *); 66 68 67 69 #endif
+3 -2
imap-send.c
··· 1323 1323 return 1; 1324 1324 } 1325 1325 1326 - static int git_imap_config(const char *var, const char *val, void *cb) 1326 + static int git_imap_config(const char *var, const char *val, 1327 + const struct config_context *ctx, void *cb) 1327 1328 { 1328 1329 1329 1330 if (!strcmp("imap.sslverify", var)) ··· 1357 1358 server.host = xstrdup(val); 1358 1359 } 1359 1360 } else 1360 - return git_default_config(var, val, cb); 1361 + return git_default_config(var, val, ctx, cb); 1361 1362 1362 1363 return 0; 1363 1364 }
+1
ll-merge.c
··· 254 254 static const char *default_ll_merge; 255 255 256 256 static int read_merge_config(const char *var, const char *value, 257 + const struct config_context *ctx UNUSED, 257 258 void *cb UNUSED) 258 259 { 259 260 struct ll_merge_driver *fn;
+1
ls-refs.c
··· 137 137 } 138 138 139 139 static int ls_refs_config(const char *var, const char *value, 140 + const struct config_context *ctx UNUSED, 140 141 void *cb_data) 141 142 { 142 143 struct ls_refs_data *data = cb_data;
+3 -2
mailinfo.c
··· 1241 1241 return 0; 1242 1242 } 1243 1243 1244 - static int git_mailinfo_config(const char *var, const char *value, void *mi_) 1244 + static int git_mailinfo_config(const char *var, const char *value, 1245 + const struct config_context *ctx, void *mi_) 1245 1246 { 1246 1247 struct mailinfo *mi = mi_; 1247 1248 1248 1249 if (!starts_with(var, "mailinfo.")) 1249 - return git_default_config(var, value, NULL); 1250 + return git_default_config(var, value, ctx, NULL); 1250 1251 if (!strcmp(var, "mailinfo.scissors")) { 1251 1252 mi->use_scissors = git_config_bool(var, value); 1252 1253 return 0;
+3 -1
notes-utils.c
··· 94 94 return NULL; 95 95 } 96 96 97 - static int notes_rewrite_config(const char *k, const char *v, void *cb) 97 + static int notes_rewrite_config(const char *k, const char *v, 98 + const struct config_context *ctx UNUSED, 99 + void *cb) 98 100 { 99 101 struct notes_rewrite_cfg *c = cb; 100 102 if (starts_with(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
+3 -1
notes.c
··· 974 974 free(globs_copy); 975 975 } 976 976 977 - static int notes_display_config(const char *k, const char *v, void *cb) 977 + static int notes_display_config(const char *k, const char *v, 978 + const struct config_context *ctx UNUSED, 979 + void *cb) 978 980 { 979 981 int *load_refs = cb; 980 982
+4 -1
pager.c
··· 43 43 } 44 44 45 45 static int core_pager_config(const char *var, const char *value, 46 + const struct config_context *ctx UNUSED, 46 47 void *data UNUSED) 47 48 { 48 49 if (!strcmp(var, "core.pager")) ··· 228 229 char *value; 229 230 }; 230 231 231 - static int pager_command_config(const char *var, const char *value, void *vdata) 232 + static int pager_command_config(const char *var, const char *value, 233 + const struct config_context *ctx UNUSED, 234 + void *vdata) 232 235 { 233 236 struct pager_command_config_data *data = vdata; 234 237 const char *cmd;
+1
pretty.c
··· 56 56 } 57 57 58 58 static int git_pretty_formats_config(const char *var, const char *value, 59 + const struct config_context *ctx UNUSED, 59 60 void *cb UNUSED) 60 61 { 61 62 struct cmt_fmt_map *commit_format = NULL;
+3 -1
promisor-remote.c
··· 100 100 config->promisors_tail = &r->next; 101 101 } 102 102 103 - static int promisor_remote_config(const char *var, const char *value, void *data) 103 + static int promisor_remote_config(const char *var, const char *value, 104 + const struct config_context *ctx UNUSED, 105 + void *data) 104 106 { 105 107 struct promisor_remote_config *config = data; 106 108 const char *name;
+2 -1
remote.c
··· 349 349 remote->fetch_tags = 1; /* always auto-follow */ 350 350 } 351 351 352 - static int handle_config(const char *key, const char *value, void *cb) 352 + static int handle_config(const char *key, const char *value, 353 + const struct config_context *ctx UNUSED, void *cb) 353 354 { 354 355 const char *name; 355 356 size_t namelen;
+3 -1
revision.c
··· 1572 1572 const char *section; 1573 1573 }; 1574 1574 1575 - static int hide_refs_config(const char *var, const char *value, void *cb_data) 1575 + static int hide_refs_config(const char *var, const char *value, 1576 + const struct config_context *ctx UNUSED, 1577 + void *cb_data) 1576 1578 { 1577 1579 struct exclude_hidden_refs_cb *cb = cb_data; 1578 1580 cb->exclusions->hidden_refs_configured = 1;
+3 -1
scalar.c
··· 594 594 return register_dir(); 595 595 } 596 596 597 - static int get_scalar_repos(const char *key, const char *value, void *data) 597 + static int get_scalar_repos(const char *key, const char *value, 598 + const struct config_context *ctx UNUSED, 599 + void *data) 598 600 { 599 601 struct string_list *list = data; 600 602
+6 -3
sequencer.c
··· 219 219 return rec; 220 220 } 221 221 222 - static int git_sequencer_config(const char *k, const char *v, void *cb) 222 + static int git_sequencer_config(const char *k, const char *v, 223 + const struct config_context *ctx, void *cb) 223 224 { 224 225 struct replay_opts *opts = cb; 225 226 int status; ··· 274 275 if (opts->action == REPLAY_REVERT && !strcmp(k, "revert.reference")) 275 276 opts->commit_use_reference = git_config_bool(k, v); 276 277 277 - return git_diff_basic_config(k, v, NULL); 278 + return git_diff_basic_config(k, v, ctx, NULL); 278 279 } 279 280 280 281 void sequencer_init_config(struct replay_opts *opts) ··· 2881 2882 return 0; 2882 2883 } 2883 2884 2884 - static int populate_opts_cb(const char *key, const char *value, void *data) 2885 + static int populate_opts_cb(const char *key, const char *value, 2886 + const struct config_context *ctx UNUSED, 2887 + void *data) 2885 2888 { 2886 2889 struct replay_opts *opts = data; 2887 2890 int error_flag = 1;
+11 -5
setup.c
··· 517 517 startup_info->original_cwd = NULL; 518 518 } 519 519 520 - static int read_worktree_config(const char *var, const char *value, void *vdata) 520 + static int read_worktree_config(const char *var, const char *value, 521 + const struct config_context *ctx UNUSED, 522 + void *vdata) 521 523 { 522 524 struct repository_format *data = vdata; 523 525 ··· 588 590 return EXTENSION_UNKNOWN; 589 591 } 590 592 591 - static int check_repo_format(const char *var, const char *value, void *vdata) 593 + static int check_repo_format(const char *var, const char *value, 594 + const struct config_context *ctx, void *vdata) 592 595 { 593 596 struct repository_format *data = vdata; 594 597 const char *ext; ··· 617 620 } 618 621 } 619 622 620 - return read_worktree_config(var, value, vdata); 623 + return read_worktree_config(var, value, ctx, vdata); 621 624 } 622 625 623 626 static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok) ··· 1115 1118 int is_safe; 1116 1119 }; 1117 1120 1118 - static int safe_directory_cb(const char *key, const char *value, void *d) 1121 + static int safe_directory_cb(const char *key, const char *value, 1122 + const struct config_context *ctx UNUSED, void *d) 1119 1123 { 1120 1124 struct safe_directory_data *data = d; 1121 1125 ··· 1171 1175 return data.is_safe; 1172 1176 } 1173 1177 1174 - static int allowed_bare_repo_cb(const char *key, const char *value, void *d) 1178 + static int allowed_bare_repo_cb(const char *key, const char *value, 1179 + const struct config_context *ctx UNUSED, 1180 + void *d) 1175 1181 { 1176 1182 enum allowed_bare_repo *allowed_bare_repo = d; 1177 1183
+12 -5
submodule-config.c
··· 426 426 * config store (.git/config, etc). Callers are responsible for 427 427 * checking for overrides in the main config store when appropriate. 428 428 */ 429 - static int parse_config(const char *var, const char *value, void *data) 429 + static int parse_config(const char *var, const char *value, 430 + const struct config_context *ctx UNUSED, void *data) 430 431 { 431 432 struct parse_config_parameter *me = data; 432 433 struct submodule *submodule; ··· 674 675 } 675 676 } 676 677 677 - static int gitmodules_cb(const char *var, const char *value, void *data) 678 + static int gitmodules_cb(const char *var, const char *value, 679 + const struct config_context *ctx, void *data) 678 680 { 679 681 struct repository *repo = data; 680 682 struct parse_config_parameter parameter; ··· 684 686 parameter.gitmodules_oid = null_oid(); 685 687 parameter.overwrite = 1; 686 688 687 - return parse_config(var, value, &parameter); 689 + return parse_config(var, value, ctx, &parameter); 688 690 } 689 691 690 692 void repo_read_gitmodules(struct repository *repo, int skip_if_read) ··· 801 803 submodule_cache_clear(r->submodule_cache); 802 804 } 803 805 804 - static int config_print_callback(const char *var, const char *value, void *cb_data) 806 + static int config_print_callback(const char *var, const char *value, 807 + const struct config_context *ctx UNUSED, 808 + void *cb_data) 805 809 { 806 810 char *wanted_key = cb_data; 807 811 ··· 843 847 int *recurse_submodules; 844 848 }; 845 849 846 - static int gitmodules_fetch_config(const char *var, const char *value, void *cb) 850 + static int gitmodules_fetch_config(const char *var, const char *value, 851 + const struct config_context *ctx UNUSED, 852 + void *cb) 847 853 { 848 854 struct fetch_config *config = cb; 849 855 if (!strcmp(var, "submodule.fetchjobs")) { ··· 871 877 } 872 878 873 879 static int gitmodules_update_clone_config(const char *var, const char *value, 880 + const struct config_context *ctx UNUSED, 874 881 void *cb) 875 882 { 876 883 int *max_jobs = cb;
+8 -3
t/helper/test-config.c
··· 42 42 * 43 43 */ 44 44 45 - static int iterate_cb(const char *var, const char *value, void *data UNUSED) 45 + static int iterate_cb(const char *var, const char *value, 46 + const struct config_context *ctx UNUSED, 47 + void *data UNUSED) 46 48 { 47 49 static int nr; 48 50 ··· 59 61 return 0; 60 62 } 61 63 62 - static int parse_int_cb(const char *var, const char *value, void *data) 64 + static int parse_int_cb(const char *var, const char *value, 65 + const struct config_context *ctx UNUSED, void *data) 63 66 { 64 67 const char *key_to_match = data; 65 68 ··· 70 73 return 0; 71 74 } 72 75 73 - static int early_config_cb(const char *var, const char *value, void *vdata) 76 + static int early_config_cb(const char *var, const char *value, 77 + const struct config_context *ctx UNUSED, 78 + void *vdata) 74 79 { 75 80 const char *key = vdata; 76 81
+3 -1
t/helper/test-userdiff.c
··· 12 12 return 0; 13 13 } 14 14 15 - static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED) 15 + static int cmd__userdiff_config(const char *var, const char *value, 16 + const struct config_context *ctx UNUSED, 17 + void *cb UNUSED) 16 18 { 17 19 if (userdiff_config(var, value) < 0) 18 20 return -1;
+7 -2
trace2/tr2_cfg.c
··· 99 99 /* 100 100 * See if the given config key matches any of our patterns of interest. 101 101 */ 102 - static int tr2_cfg_cb(const char *key, const char *value, void *d) 102 + static int tr2_cfg_cb(const char *key, const char *value, 103 + const struct config_context *ctx UNUSED, void *d) 103 104 { 104 105 struct strbuf **s; 105 106 struct tr2_cfg_data *data = (struct tr2_cfg_data *)d; ··· 142 143 void tr2_cfg_set_fl(const char *file, int line, const char *key, 143 144 const char *value) 144 145 { 146 + struct key_value_info kvi = KVI_INIT; 147 + struct config_context ctx = { 148 + .kvi = &kvi, 149 + }; 145 150 struct tr2_cfg_data data = { file, line }; 146 151 147 152 if (tr2_cfg_load_patterns() > 0) 148 - tr2_cfg_cb(key, value, &data); 153 + tr2_cfg_cb(key, value, &ctx, &data); 149 154 }
+2 -1
trace2/tr2_sysenv.c
··· 57 57 }; 58 58 /* clang-format on */ 59 59 60 - static int tr2_sysenv_cb(const char *key, const char *value, void *d) 60 + static int tr2_sysenv_cb(const char *key, const char *value, 61 + const struct config_context *ctx UNUSED, void *d) 61 62 { 62 63 int k; 63 64
+2
trailer.c
··· 482 482 }; 483 483 484 484 static int git_trailer_default_config(const char *conf_key, const char *value, 485 + const struct config_context *ctx UNUSED, 485 486 void *cb UNUSED) 486 487 { 487 488 const char *trailer_item, *variable_name; ··· 514 515 } 515 516 516 517 static int git_trailer_config(const char *conf_key, const char *value, 518 + const struct config_context *ctx UNUSED, 517 519 void *cb UNUSED) 518 520 { 519 521 const char *trailer_item, *variable_name;
+6 -2
upload-pack.c
··· 1309 1309 return 0; 1310 1310 } 1311 1311 1312 - static int upload_pack_config(const char *var, const char *value, void *cb_data) 1312 + static int upload_pack_config(const char *var, const char *value, 1313 + const struct config_context *ctx UNUSED, 1314 + void *cb_data) 1313 1315 { 1314 1316 struct upload_pack_data *data = cb_data; 1315 1317 ··· 1350 1352 return parse_hide_refs_config(var, value, "uploadpack", &data->hidden_refs); 1351 1353 } 1352 1354 1353 - static int upload_pack_protected_config(const char *var, const char *value, void *cb_data) 1355 + static int upload_pack_protected_config(const char *var, const char *value, 1356 + const struct config_context *ctx UNUSED, 1357 + void *cb_data) 1354 1358 { 1355 1359 struct upload_pack_data *data = cb_data; 1356 1360
+4 -3
urlmatch.c
··· 551 551 return 0; 552 552 } 553 553 554 - int urlmatch_config_entry(const char *var, const char *value, void *cb) 554 + int urlmatch_config_entry(const char *var, const char *value, 555 + const struct config_context *ctx, void *cb) 555 556 { 556 557 struct string_list_item *item; 557 558 struct urlmatch_config *collect = cb; ··· 565 566 566 567 if (!skip_prefix(var, collect->section, &key) || *(key++) != '.') { 567 568 if (collect->cascade_fn) 568 - return collect->cascade_fn(var, value, cb); 569 + return collect->cascade_fn(var, value, ctx, cb); 569 570 return 0; /* not interested */ 570 571 } 571 572 dot = strrchr(key, '.'); ··· 609 610 strbuf_addstr(&synthkey, collect->section); 610 611 strbuf_addch(&synthkey, '.'); 611 612 strbuf_addstr(&synthkey, key); 612 - retval = collect->collect_fn(synthkey.buf, value, collect->cb); 613 + retval = collect->collect_fn(synthkey.buf, value, ctx, collect->cb); 613 614 614 615 strbuf_release(&synthkey); 615 616 return retval;
+2 -1
urlmatch.h
··· 71 71 .vars = STRING_LIST_INIT_DUP, \ 72 72 } 73 73 74 - int urlmatch_config_entry(const char *var, const char *value, void *cb); 74 + int urlmatch_config_entry(const char *var, const char *value, 75 + const struct config_context *ctx, void *cb); 75 76 void urlmatch_config_release(struct urlmatch_config *config); 76 77 77 78 #endif /* URL_MATCH_H */
+3 -2
xdiff-interface.c
··· 307 307 308 308 int git_xmerge_style = -1; 309 309 310 - int git_xmerge_config(const char *var, const char *value, void *cb) 310 + int git_xmerge_config(const char *var, const char *value, 311 + const struct config_context *ctx, void *cb) 311 312 { 312 313 if (!strcmp(var, "merge.conflictstyle")) { 313 314 if (!value) ··· 327 328 value, var); 328 329 return 0; 329 330 } 330 - return git_default_config(var, value, cb); 331 + return git_default_config(var, value, ctx, cb); 331 332 }
+3 -1
xdiff-interface.h
··· 50 50 51 51 void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags); 52 52 void xdiff_clear_find_func(xdemitconf_t *xecfg); 53 - int git_xmerge_config(const char *var, const char *value, void *cb); 53 + struct config_context; 54 + int git_xmerge_config(const char *var, const char *value, 55 + const struct config_context *ctx, void *cb); 54 56 extern int git_xmerge_style; 55 57 56 58 /*