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>
This commit is contained in:
parent
f9dbb64fad
commit
1ff21c05ba
52
config.c
52
config.c
@ -332,7 +332,7 @@ int git_config_include(const char *var, const char *value, void *data)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_config_push_parameter(const char *text)
|
static void git_config_push_split_parameter(const char *key, const char *value)
|
||||||
{
|
{
|
||||||
struct strbuf env = STRBUF_INIT;
|
struct strbuf env = STRBUF_INIT;
|
||||||
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
|
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
|
||||||
@ -340,20 +340,60 @@ void git_config_push_parameter(const char *text)
|
|||||||
strbuf_addstr(&env, old);
|
strbuf_addstr(&env, old);
|
||||||
strbuf_addch(&env, ' ');
|
strbuf_addch(&env, ' ');
|
||||||
}
|
}
|
||||||
sq_quote_buf(&env, text);
|
sq_quote_buf(&env, key);
|
||||||
|
strbuf_addch(&env, '=');
|
||||||
|
if (value)
|
||||||
|
sq_quote_buf(&env, value);
|
||||||
setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
|
setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
|
||||||
strbuf_release(&env);
|
strbuf_release(&env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void git_config_push_parameter(const char *text)
|
||||||
|
{
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we see:
|
||||||
|
*
|
||||||
|
* section.subsection=with=equals.key=value
|
||||||
|
*
|
||||||
|
* we cannot tell if it means:
|
||||||
|
*
|
||||||
|
* [section "subsection=with=equals"]
|
||||||
|
* key = value
|
||||||
|
*
|
||||||
|
* or:
|
||||||
|
*
|
||||||
|
* [section]
|
||||||
|
* subsection = with=equals.key=value
|
||||||
|
*
|
||||||
|
* We parse left-to-right for the first "=", meaning we'll prefer to
|
||||||
|
* keep the value intact over the subsection. This is historical, but
|
||||||
|
* also sensible since values are more likely to contain odd or
|
||||||
|
* untrusted input than a section name.
|
||||||
|
*
|
||||||
|
* A missing equals is explicitly allowed (as a bool-only entry).
|
||||||
|
*/
|
||||||
|
value = strchr(text, '=');
|
||||||
|
if (value) {
|
||||||
|
char *key = xmemdupz(text, value - text);
|
||||||
|
git_config_push_split_parameter(key, value + 1);
|
||||||
|
free(key);
|
||||||
|
} else {
|
||||||
|
git_config_push_split_parameter(text, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void git_config_push_env(const char *spec)
|
void git_config_push_env(const char *spec)
|
||||||
{
|
{
|
||||||
struct strbuf buf = STRBUF_INIT;
|
char *key;
|
||||||
const char *env_name;
|
const char *env_name;
|
||||||
const char *env_value;
|
const char *env_value;
|
||||||
|
|
||||||
env_name = strrchr(spec, '=');
|
env_name = strrchr(spec, '=');
|
||||||
if (!env_name)
|
if (!env_name)
|
||||||
die(_("invalid config format: %s"), spec);
|
die(_("invalid config format: %s"), spec);
|
||||||
|
key = xmemdupz(spec, env_name - spec);
|
||||||
env_name++;
|
env_name++;
|
||||||
if (!*env_name)
|
if (!*env_name)
|
||||||
die(_("missing environment variable name for configuration '%.*s'"),
|
die(_("missing environment variable name for configuration '%.*s'"),
|
||||||
@ -364,10 +404,8 @@ void git_config_push_env(const char *spec)
|
|||||||
die(_("missing environment variable '%s' for configuration '%.*s'"),
|
die(_("missing environment variable '%s' for configuration '%.*s'"),
|
||||||
env_name, (int)(env_name - spec - 1), spec);
|
env_name, (int)(env_name - spec - 1), spec);
|
||||||
|
|
||||||
strbuf_add(&buf, spec, env_name - spec);
|
git_config_push_split_parameter(key, env_value);
|
||||||
strbuf_addstr(&buf, env_value);
|
free(key);
|
||||||
git_config_push_parameter(buf.buf);
|
|
||||||
strbuf_release(&buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int iskeychar(int c)
|
static inline int iskeychar(int c)
|
||||||
|
@ -1416,6 +1416,14 @@ test_expect_success 'git -c and --config-env override each other' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--config-env handles keys with equals' '
|
||||||
|
echo value=with=equals >expect &&
|
||||||
|
ENVVAR=value=with=equals git \
|
||||||
|
--config-env=section.subsection=with=equals.key=ENVVAR \
|
||||||
|
config section.subsection=with=equals.key >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'git config --edit works' '
|
test_expect_success 'git config --edit works' '
|
||||||
git config -f tmp test.value no &&
|
git config -f tmp test.value no &&
|
||||||
echo test.value=yes >expect &&
|
echo test.value=yes >expect &&
|
||||||
|
Loading…
Reference in New Issue
Block a user