Skip to content

Commit 26b6693

Browse files
chooglengitster
authored andcommitted
config.c: pass ctx with CLI config
Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters(). Plumbing "kvi" reveals a few places where we've been doing the wrong thing: * git_config_parse_parameter() hasn't been setting config source information, so plumb "kvi" there too. * Several sites in builtin/config.c have been calling current_config_*() functions outside of config callbacks (indirectly, via the format_config() helper), which means they're reading state that isn't set correctly: * "git config --get-urlmatch --show-scope" iterates config to collect values, but then attempts to display the scope after config iteration, causing the "unknown" scope to be shown instead of the config file's scope. It's clear that this wasn't intended: we knew that "--get-urlmatch" couldn't show config source metadata, which is why "--show-origin" was marked incompatible with "--get-urlmatch" when it was introduced [1]. It was most likely a mistake that we allowed "--show-scope" to sneak through. Fix this by copying the "kvi" value in the collection phase so that it can be read back later. This means that we can now support "git config --get-urlmatch --show-origin", but that is left unchanged for now. * "git config --default" doesn't have config source metadata when displaying the default value, so "--show-scope" also results in "unknown", and "--show-origin" results in a BUG(). Fix this by treating the default value as if it came from the command line (e.g. like we do with "git -c" or "git config --file"), using kvi_from_param(). [1] https://lore.kernel.org/git/[email protected]/ Signed-off-by: Glen Choo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 809d868 commit 26b6693

File tree

4 files changed

+99
-58
lines changed

4 files changed

+99
-58
lines changed

builtin/config.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -194,38 +194,42 @@ static void check_argc(int argc, int min, int max)
194194
usage_builtin_config();
195195
}
196196

197-
static void show_config_origin(struct strbuf *buf)
197+
static void show_config_origin(const struct key_value_info *kvi,
198+
struct strbuf *buf)
198199
{
199200
const char term = end_nul ? '\0' : '\t';
200201

201-
strbuf_addstr(buf, current_config_origin_type());
202+
strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
202203
strbuf_addch(buf, ':');
203204
if (end_nul)
204-
strbuf_addstr(buf, current_config_name());
205+
strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
205206
else
206-
quote_c_style(current_config_name(), buf, NULL, 0);
207+
quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
207208
strbuf_addch(buf, term);
208209
}
209210

210-
static void show_config_scope(struct strbuf *buf)
211+
static void show_config_scope(const struct key_value_info *kvi,
212+
struct strbuf *buf)
211213
{
212214
const char term = end_nul ? '\0' : '\t';
213-
const char *scope = config_scope_name(current_config_scope());
215+
const char *scope = config_scope_name(kvi->scope);
214216

215217
strbuf_addstr(buf, N_(scope));
216218
strbuf_addch(buf, term);
217219
}
218220

219221
static int show_all_config(const char *key_, const char *value_,
220-
const struct config_context *ctx UNUSED,
222+
const struct config_context *ctx,
221223
void *cb UNUSED)
222224
{
225+
const struct key_value_info *kvi = ctx->kvi;
226+
223227
if (show_origin || show_scope) {
224228
struct strbuf buf = STRBUF_INIT;
225229
if (show_scope)
226-
show_config_scope(&buf);
230+
show_config_scope(kvi, &buf);
227231
if (show_origin)
228-
show_config_origin(&buf);
232+
show_config_origin(kvi, &buf);
229233
/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
230234
fwrite(buf.buf, 1, buf.len, stdout);
231235
strbuf_release(&buf);
@@ -243,12 +247,13 @@ struct strbuf_list {
243247
int alloc;
244248
};
245249

246-
static int format_config(struct strbuf *buf, const char *key_, const char *value_)
250+
static int format_config(struct strbuf *buf, const char *key_,
251+
const char *value_, const struct key_value_info *kvi)
247252
{
248253
if (show_scope)
249-
show_config_scope(buf);
254+
show_config_scope(kvi, buf);
250255
if (show_origin)
251-
show_config_origin(buf);
256+
show_config_origin(kvi, buf);
252257
if (show_keys)
253258
strbuf_addstr(buf, key_);
254259
if (!omit_values) {
@@ -303,9 +308,10 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
303308
}
304309

305310
static int collect_config(const char *key_, const char *value_,
306-
const struct config_context *ctx UNUSED, void *cb)
311+
const struct config_context *ctx, void *cb)
307312
{
308313
struct strbuf_list *values = cb;
314+
const struct key_value_info *kvi = ctx->kvi;
309315

310316
if (!use_key_regexp && strcmp(key_, key))
311317
return 0;
@@ -320,7 +326,7 @@ static int collect_config(const char *key_, const char *value_,
320326
ALLOC_GROW(values->items, values->nr + 1, values->alloc);
321327
strbuf_init(&values->items[values->nr], 0);
322328

323-
return format_config(&values->items[values->nr++], key_, value_);
329+
return format_config(&values->items[values->nr++], key_, value_, kvi);
324330
}
325331

326332
static int get_value(const char *key_, const char *regex_, unsigned flags)
@@ -382,11 +388,14 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
382388
&config_options);
383389

384390
if (!values.nr && default_value) {
391+
struct key_value_info kvi = KVI_INIT;
385392
struct strbuf *item;
393+
394+
kvi_from_param(&kvi);
386395
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
387396
item = &values.items[values.nr++];
388397
strbuf_init(item, 0);
389-
if (format_config(item, key_, default_value) < 0)
398+
if (format_config(item, key_, default_value, &kvi) < 0)
390399
die(_("failed to format default config value: %s"),
391400
default_value);
392401
}
@@ -563,15 +572,17 @@ static void check_write(void)
563572
struct urlmatch_current_candidate_value {
564573
char value_is_null;
565574
struct strbuf value;
575+
struct key_value_info kvi;
566576
};
567577

568578
static int urlmatch_collect_fn(const char *var, const char *value,
569-
const struct config_context *ctx UNUSED,
579+
const struct config_context *ctx,
570580
void *cb)
571581
{
572582
struct string_list *values = cb;
573583
struct string_list_item *item = string_list_insert(values, var);
574584
struct urlmatch_current_candidate_value *matched = item->util;
585+
const struct key_value_info *kvi = ctx->kvi;
575586

576587
if (!matched) {
577588
matched = xmalloc(sizeof(*matched));
@@ -580,6 +591,7 @@ static int urlmatch_collect_fn(const char *var, const char *value,
580591
} else {
581592
strbuf_reset(&matched->value);
582593
}
594+
matched->kvi = *kvi;
583595

584596
if (value) {
585597
strbuf_addstr(&matched->value, value);
@@ -627,7 +639,8 @@ static int get_urlmatch(const char *var, const char *url)
627639
struct strbuf buf = STRBUF_INIT;
628640

629641
format_config(&buf, item->string,
630-
matched->value_is_null ? NULL : matched->value.buf);
642+
matched->value_is_null ? NULL : matched->value.buf,
643+
&matched->kvi);
631644
fwrite(buf.buf, 1, buf.len, stdout);
632645
strbuf_release(&buf);
633646

config.c

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ static const char include_depth_advice[] = N_(
219219
"from\n"
220220
" %s\n"
221221
"This might be due to circular includes.");
222-
static int handle_path_include(struct config_source *cs, const char *path,
222+
static int handle_path_include(struct config_source *cs,
223+
const struct key_value_info *kvi,
224+
const char *path,
223225
struct config_include_data *inc)
224226
{
225227
int ret = 0;
@@ -260,8 +262,7 @@ static int handle_path_include(struct config_source *cs, const char *path,
260262
cs->name ? cs->name :
261263
"the command line");
262264
ret = git_config_from_file_with_options(git_config_include, path, inc,
263-
current_config_scope(),
264-
NULL);
265+
kvi->scope, NULL);
265266
inc->depth--;
266267
}
267268
cleanup:
@@ -510,7 +511,7 @@ static int git_config_include(const char *var, const char *value,
510511
return ret;
511512

512513
if (!strcmp(var, "include.path"))
513-
ret = handle_path_include(cs, value, inc);
514+
ret = handle_path_include(cs, ctx->kvi, value, inc);
514515

515516
if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
516517
cond && include_condition_is_true(cs, inc, cond, cond_len) &&
@@ -519,7 +520,7 @@ static int git_config_include(const char *var, const char *value,
519520

520521
if (inc->opts->unconditional_remote_url)
521522
inc->fn = forbid_remote_url;
522-
ret = handle_path_include(cs, value, inc);
523+
ret = handle_path_include(cs, ctx->kvi, value, inc);
523524
inc->fn = old_fn;
524525
}
525526

@@ -677,27 +678,44 @@ int git_config_parse_key(const char *key, char **store_key, size_t *baselen_)
677678
}
678679

679680
static int config_parse_pair(const char *key, const char *value,
680-
config_fn_t fn, void *data)
681+
struct key_value_info *kvi,
682+
config_fn_t fn, void *data)
681683
{
682684
char *canonical_name;
683685
int ret;
686+
struct config_context ctx = {
687+
.kvi = kvi,
688+
};
684689

685690
if (!strlen(key))
686691
return error(_("empty config key"));
687692
if (git_config_parse_key(key, &canonical_name, NULL))
688693
return -1;
689694

690-
ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0;
695+
ret = (fn(canonical_name, value, &ctx, data) < 0) ? -1 : 0;
691696
free(canonical_name);
692697
return ret;
693698
}
694699

700+
701+
/* for values read from `git_config_from_parameters()` */
702+
void kvi_from_param(struct key_value_info *out)
703+
{
704+
out->filename = NULL;
705+
out->linenr = -1;
706+
out->origin_type = CONFIG_ORIGIN_CMDLINE;
707+
out->scope = CONFIG_SCOPE_COMMAND;
708+
}
709+
695710
int git_config_parse_parameter(const char *text,
696711
config_fn_t fn, void *data)
697712
{
698713
const char *value;
699714
struct strbuf **pair;
700715
int ret;
716+
struct key_value_info kvi = KVI_INIT;
717+
718+
kvi_from_param(&kvi);
701719

702720
pair = strbuf_split_str(text, '=', 2);
703721
if (!pair[0])
@@ -716,12 +734,13 @@ int git_config_parse_parameter(const char *text,
716734
return error(_("bogus config parameter: %s"), text);
717735
}
718736

719-
ret = config_parse_pair(pair[0]->buf, value, fn, data);
737+
ret = config_parse_pair(pair[0]->buf, value, &kvi, fn, data);
720738
strbuf_list_free(pair);
721739
return ret;
722740
}
723741

724-
static int parse_config_env_list(char *env, config_fn_t fn, void *data)
742+
static int parse_config_env_list(char *env, struct key_value_info *kvi,
743+
config_fn_t fn, void *data)
725744
{
726745
char *cur = env;
727746
while (cur && *cur) {
@@ -755,7 +774,7 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data)
755774
CONFIG_DATA_ENVIRONMENT);
756775
}
757776

758-
if (config_parse_pair(key, value, fn, data) < 0)
777+
if (config_parse_pair(key, value, kvi, fn, data) < 0)
759778
return -1;
760779
}
761780
else {
@@ -780,10 +799,13 @@ int git_config_from_parameters(config_fn_t fn, void *data)
780799
int ret = 0;
781800
char *envw = NULL;
782801
struct config_source source = CONFIG_SOURCE_INIT;
802+
struct key_value_info kvi = KVI_INIT;
783803

784804
source.origin_type = CONFIG_ORIGIN_CMDLINE;
785805
config_reader_push_source(&the_reader, &source);
786806

807+
kvi_from_param(&kvi);
808+
787809
env = getenv(CONFIG_COUNT_ENVIRONMENT);
788810
if (env) {
789811
unsigned long count;
@@ -819,7 +841,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
819841
}
820842
strbuf_reset(&envvar);
821843

822-
if (config_parse_pair(key, value, fn, data) < 0) {
844+
if (config_parse_pair(key, value, &kvi, fn, data) < 0) {
823845
ret = -1;
824846
goto out;
825847
}
@@ -830,7 +852,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
830852
if (env) {
831853
/* sq_dequote will write over it */
832854
envw = xstrdup(env);
833-
if (parse_config_env_list(envw, fn, data) < 0) {
855+
if (parse_config_env_list(envw, &kvi, fn, data) < 0) {
834856
ret = -1;
835857
goto out;
836858
}
@@ -2442,7 +2464,8 @@ static int configset_find_element(struct config_set *set, const char *key,
24422464
return 0;
24432465
}
24442466

2445-
static int configset_add_value(struct config_reader *reader,
2467+
static int configset_add_value(const struct key_value_info *kvi_p,
2468+
struct config_reader *reader,
24462469
struct config_set *set, const char *key,
24472470
const char *value)
24482471
{
@@ -2476,13 +2499,9 @@ static int configset_add_value(struct config_reader *reader,
24762499
if (!reader->source)
24772500
BUG("configset_add_value has no source");
24782501
if (reader->source->name) {
2479-
kvi_from_source(reader->source, current_config_scope(), kv_info);
2502+
kvi_from_source(reader->source, kvi_p->scope, kv_info);
24802503
} else {
2481-
/* for values read from `git_config_from_parameters()` */
2482-
kv_info->filename = NULL;
2483-
kv_info->linenr = -1;
2484-
kv_info->origin_type = CONFIG_ORIGIN_CMDLINE;
2485-
kv_info->scope = reader->parsing_scope;
2504+
kvi_from_param(kv_info);
24862505
}
24872506
si->util = kv_info;
24882507

@@ -2538,11 +2557,12 @@ struct configset_add_data {
25382557
#define CONFIGSET_ADD_INIT { 0 }
25392558

25402559
static int config_set_callback(const char *key, const char *value,
2541-
const struct config_context *ctx UNUSED,
2560+
const struct config_context *ctx,
25422561
void *cb)
25432562
{
25442563
struct configset_add_data *data = cb;
2545-
configset_add_value(data->config_reader, data->config_set, key, value);
2564+
configset_add_value(ctx->kvi, data->config_reader, data->config_set,
2565+
key, value);
25462566
return 0;
25472567
}
25482568

@@ -4037,16 +4057,6 @@ const char *config_origin_type_name(enum config_origin_type type)
40374057
}
40384058
}
40394059

4040-
const char *current_config_origin_type(void)
4041-
{
4042-
enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN;
4043-
4044-
if (reader_origin_type(&the_reader, &type))
4045-
BUG("current_config_origin_type called outside config callback");
4046-
4047-
return config_origin_type_name(type);
4048-
}
4049-
40504060
const char *config_scope_name(enum config_scope scope)
40514061
{
40524062
switch (scope) {
@@ -4078,14 +4088,6 @@ static int reader_config_name(struct config_reader *reader, const char **out)
40784088
return 0;
40794089
}
40804090

4081-
const char *current_config_name(void)
4082-
{
4083-
const char *name;
4084-
if (reader_config_name(&the_reader, &name))
4085-
BUG("current_config_name called outside config callback");
4086-
return name ? name : "";
4087-
}
4088-
40894091
enum config_scope current_config_scope(void)
40904092
{
40914093
if (the_reader.config_kvi)

config.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,8 @@ void git_global_config(char **user, char **xdg);
387387
int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
388388

389389
enum config_scope current_config_scope(void);
390-
const char *current_config_origin_type(void);
391-
const char *current_config_name(void);
392390
const char *config_origin_type_name(enum config_origin_type type);
391+
void kvi_from_param(struct key_value_info *out);
393392

394393
/*
395394
* Match and parse a config key of the form:

0 commit comments

Comments
 (0)