aboutsummaryrefslogtreecommitdiffstats
path: root/config.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2021-01-12 13:27:01 +0100
committerJunio C Hamano <gitster@pobox.com>2021-01-15 13:03:18 -0800
commit1ff21c05ba99ed2d0ade8318e3cb0c1a3f8d4b80 (patch)
tree5a5c333541cec7abf57326559fc958a556dadc7b /config.c
parentf9dbb64fadf599c588a39d2251bb3f9a2f7d572a (diff)
downloadgit-1ff21c05ba99ed2d0ade8318e3cb0c1a3f8d4b80.tar.gz
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>
Diffstat (limited to 'config.c')
-rw-r--r--config.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/config.c b/config.c
index dd559f060b..4a490583ad 100644
--- a/config.c
+++ b/config.c
@@ -332,7 +332,7 @@ int git_config_include(const char *var, const char *value, void *data)
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;
const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
@@ -340,20 +340,60 @@ void git_config_push_parameter(const char *text)
strbuf_addstr(&env, old);
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);
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)
{
- struct strbuf buf = STRBUF_INIT;
+ char *key;
const char *env_name;
const char *env_value;
env_name = strrchr(spec, '=');
if (!env_name)
die(_("invalid config format: %s"), spec);
+ key = xmemdupz(spec, env_name - spec);
env_name++;
if (!*env_name)
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'"),
env_name, (int)(env_name - spec - 1), spec);
- strbuf_add(&buf, spec, env_name - spec);
- strbuf_addstr(&buf, env_value);
- git_config_push_parameter(buf.buf);
- strbuf_release(&buf);
+ git_config_push_split_parameter(key, env_value);
+ free(key);
}
static inline int iskeychar(int c)