Skip to content

Commit 1ff21c0

Browse files
pks-tgitster
authored andcommitted
config: store "git -c" variables using more robust format
The previous commit added a new format for $GIT_CONFIG_PARAMETERS which is able to robustly handle subsections with "=" in them. Let's start writing the new format. Unfortunately, this does much less than you'd hope, because "git -c" itself has the same ambiguity problem! But it's still worth doing: - we've now pushed the problem from the inter-process communication into the "-c" command-line parser. This would free us up to later add an unambiguous format there (e.g., separate arguments like "git --config key value", etc). - for --config-env, the parser already disallows "=" in the environment variable name. So: git --config-env section.with=equals.key=ENVVAR will robustly set section.with=equals.key to the contents of $ENVVAR. The new test shows the improvement for --config-env. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent f9dbb64 commit 1ff21c0

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

config.c

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -332,28 +332,68 @@ int git_config_include(const char *var, const char *value, void *data)
332332
return ret;
333333
}
334334

335-
void git_config_push_parameter(const char *text)
335+
static void git_config_push_split_parameter(const char *key, const char *value)
336336
{
337337
struct strbuf env = STRBUF_INIT;
338338
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
339339
if (old && *old) {
340340
strbuf_addstr(&env, old);
341341
strbuf_addch(&env, ' ');
342342
}
343-
sq_quote_buf(&env, text);
343+
sq_quote_buf(&env, key);
344+
strbuf_addch(&env, '=');
345+
if (value)
346+
sq_quote_buf(&env, value);
344347
setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
345348
strbuf_release(&env);
346349
}
347350

351+
void git_config_push_parameter(const char *text)
352+
{
353+
const char *value;
354+
355+
/*
356+
* When we see:
357+
*
358+
* section.subsection=with=equals.key=value
359+
*
360+
* we cannot tell if it means:
361+
*
362+
* [section "subsection=with=equals"]
363+
* key = value
364+
*
365+
* or:
366+
*
367+
* [section]
368+
* subsection = with=equals.key=value
369+
*
370+
* We parse left-to-right for the first "=", meaning we'll prefer to
371+
* keep the value intact over the subsection. This is historical, but
372+
* also sensible since values are more likely to contain odd or
373+
* untrusted input than a section name.
374+
*
375+
* A missing equals is explicitly allowed (as a bool-only entry).
376+
*/
377+
value = strchr(text, '=');
378+
if (value) {
379+
char *key = xmemdupz(text, value - text);
380+
git_config_push_split_parameter(key, value + 1);
381+
free(key);
382+
} else {
383+
git_config_push_split_parameter(text, NULL);
384+
}
385+
}
386+
348387
void git_config_push_env(const char *spec)
349388
{
350-
struct strbuf buf = STRBUF_INIT;
389+
char *key;
351390
const char *env_name;
352391
const char *env_value;
353392

354393
env_name = strrchr(spec, '=');
355394
if (!env_name)
356395
die(_("invalid config format: %s"), spec);
396+
key = xmemdupz(spec, env_name - spec);
357397
env_name++;
358398
if (!*env_name)
359399
die(_("missing environment variable name for configuration '%.*s'"),
@@ -364,10 +404,8 @@ void git_config_push_env(const char *spec)
364404
die(_("missing environment variable '%s' for configuration '%.*s'"),
365405
env_name, (int)(env_name - spec - 1), spec);
366406

367-
strbuf_add(&buf, spec, env_name - spec);
368-
strbuf_addstr(&buf, env_value);
369-
git_config_push_parameter(buf.buf);
370-
strbuf_release(&buf);
407+
git_config_push_split_parameter(key, env_value);
408+
free(key);
371409
}
372410

373411
static inline int iskeychar(int c)

t/t1300-config.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,14 @@ test_expect_success 'git -c and --config-env override each other' '
14161416
test_cmp expect actual
14171417
'
14181418

1419+
test_expect_success '--config-env handles keys with equals' '
1420+
echo value=with=equals >expect &&
1421+
ENVVAR=value=with=equals git \
1422+
--config-env=section.subsection=with=equals.key=ENVVAR \
1423+
config section.subsection=with=equals.key >actual &&
1424+
test_cmp expect actual
1425+
'
1426+
14191427
test_expect_success 'git config --edit works' '
14201428
git config -f tmp test.value no &&
14211429
echo test.value=yes >expect &&

0 commit comments

Comments
 (0)