@@ -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,30 +340,68 @@ 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++;
env_value = getenv(env_name);
if (!env_value)
die("config variable missing for '%s'", env_name);
- 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)
@@ -1361,6 +1361,14 @@ test_expect_success 'git -c and --config-env override each other' '
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' '
git config -f tmp test.value no &&
echo test.value=yes >expect &&