Skip to content

Commit 0d44a2d

Browse files
peffgitster
authored andcommitted
config: return configset value for current_config_ functions
When 473166b (config: add 'origin_type' to config_source struct, 2016-02-19) added accessor functions for the origin type and name, it taught them only to look at the "cf" struct that is filled in while we are parsing the config. This is sufficient to make it work with git-config, which uses git_config_with_options() under the hood. That function freshly parses the config files and triggers the callback when it parses each key. Most git programs, however, use git_config(). This interface will populate a cache during the actual parse, and then serve values from the cache. Calling current_config_filename() in a callback here will find a NULL cf and produce an error. There are no such callers right now, but let's prepare for adding some by making this work. We already record source information in a struct attached to each value. We just need to make it globally available and then consult it from the accessor functions. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3258258 commit 0d44a2d

File tree

4 files changed

+87
-9
lines changed

4 files changed

+87
-9
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,7 @@ extern int ignore_untracked_cache_config;
16961696
struct key_value_info {
16971697
const char *filename;
16981698
int linenr;
1699+
const char *origin_type;
16991700
};
17001701

17011702
extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));

config.c

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,24 @@ struct config_source {
3838
long (*do_ftell)(struct config_source *c);
3939
};
4040

41+
/*
42+
* These variables record the "current" config source, which
43+
* can be accessed by parsing callbacks.
44+
*
45+
* The "cf" variable will be non-NULL only when we are actually parsing a real
46+
* config source (file, blob, cmdline, etc).
47+
*
48+
* The "current_config_kvi" variable will be non-NULL only when we are feeding
49+
* cached config from a configset into a callback.
50+
*
51+
* They should generally never be non-NULL at the same time. If they are both
52+
* NULL, then we aren't parsing anything (and depending on the function looking
53+
* at the variables, it's either a bug for it to be called in the first place,
54+
* or it's a function which can be reused for non-config purposes, and should
55+
* fall back to some sane behavior).
56+
*/
4157
static struct config_source *cf;
58+
static struct key_value_info *current_config_kvi;
4259

4360
static int zlib_compression_seen;
4461

@@ -1284,16 +1301,20 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
12841301
struct string_list *values;
12851302
struct config_set_element *entry;
12861303
struct configset_list *list = &cs->list;
1287-
struct key_value_info *kv_info;
12881304

12891305
for (i = 0; i < list->nr; i++) {
12901306
entry = list->items[i].e;
12911307
value_index = list->items[i].value_index;
12921308
values = &entry->value_list;
1293-
if (fn(entry->key, values->items[value_index].string, data) < 0) {
1294-
kv_info = values->items[value_index].util;
1295-
git_die_config_linenr(entry->key, kv_info->filename, kv_info->linenr);
1296-
}
1309+
1310+
current_config_kvi = values->items[value_index].util;
1311+
1312+
if (fn(entry->key, values->items[value_index].string, data) < 0)
1313+
git_die_config_linenr(entry->key,
1314+
current_config_kvi->filename,
1315+
current_config_kvi->linenr);
1316+
1317+
current_config_kvi = NULL;
12971318
}
12981319
}
12991320

@@ -1355,10 +1376,12 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
13551376
if (cf->name) {
13561377
kv_info->filename = strintern(cf->name);
13571378
kv_info->linenr = cf->linenr;
1379+
kv_info->origin_type = strintern(cf->origin_type);
13581380
} else {
13591381
/* for values read from `git_config_from_parameters()` */
13601382
kv_info->filename = NULL;
13611383
kv_info->linenr = -1;
1384+
kv_info->origin_type = NULL;
13621385
}
13631386
si->util = kv_info;
13641387

@@ -2438,14 +2461,24 @@ int parse_config_key(const char *var,
24382461

24392462
const char *current_config_origin_type(void)
24402463
{
2441-
if (!cf)
2464+
const char *type;
2465+
if (current_config_kvi)
2466+
type = current_config_kvi->origin_type;
2467+
else if(cf)
2468+
type = cf->origin_type;
2469+
else
24422470
die("BUG: current_config_origin_type called outside config callback");
2443-
return cf->origin_type ? cf->origin_type : "command line";
2471+
return type ? type : "command line";
24442472
}
24452473

24462474
const char *current_config_name(void)
24472475
{
2448-
if (!cf)
2476+
const char *name;
2477+
if (current_config_kvi)
2478+
name = current_config_kvi->filename;
2479+
else if (cf)
2480+
name = cf->name;
2481+
else
24492482
die("BUG: current_config_name called outside config callback");
2450-
return cf->name ? cf->name : "";
2483+
return name ? name : "";
24512484
}

t/helper/test-config.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,30 @@
2525
* ascending order of priority from a config_set
2626
* constructed from files entered as arguments.
2727
*
28+
* iterate -> iterate over all values using git_config(), and print some
29+
* data for each
30+
*
2831
* Examples:
2932
*
3033
* To print the value with highest priority for key "foo.bAr Baz.rock":
3134
* test-config get_value "foo.bAr Baz.rock"
3235
*
3336
*/
3437

38+
static int iterate_cb(const char *var, const char *value, void *data)
39+
{
40+
static int nr;
41+
42+
if (nr++)
43+
putchar('\n');
44+
45+
printf("key=%s\n", var);
46+
printf("value=%s\n", value ? value : "(null)");
47+
printf("origin=%s\n", current_config_origin_type());
48+
printf("name=%s\n", current_config_name());
49+
50+
return 0;
51+
}
3552

3653
int main(int argc, char **argv)
3754
{
@@ -134,6 +151,9 @@ int main(int argc, char **argv)
134151
printf("Value not found for \"%s\"\n", argv[2]);
135152
goto exit1;
136153
}
154+
} else if (!strcmp(argv[1], "iterate")) {
155+
git_config(iterate_cb, NULL);
156+
goto exit0;
137157
}
138158

139159
die("%s: Please check the syntax and the function name", argv[0]);

t/t1308-config-set.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,28 @@ test_expect_success 'error on modifying repo config without repo' '
229229
)
230230
'
231231

232+
cmdline_config="'foo.bar=from-cmdline'"
233+
test_expect_success 'iteration shows correct origins' '
234+
echo "[foo]bar = from-repo" >.git/config &&
235+
echo "[foo]bar = from-home" >.gitconfig &&
236+
cat >expect <<-EOF &&
237+
key=foo.bar
238+
value=from-home
239+
origin=file
240+
name=$(pwd)/.gitconfig
241+
242+
key=foo.bar
243+
value=from-repo
244+
origin=file
245+
name=.git/config
246+
247+
key=foo.bar
248+
value=from-cmdline
249+
origin=command line
250+
name=
251+
EOF
252+
GIT_CONFIG_PARAMETERS=$cmdline_config test-config iterate >actual &&
253+
test_cmp expect actual
254+
'
255+
232256
test_done

0 commit comments

Comments
 (0)