git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 06/11] config.c: pass ctx with CLI config

From
Glen Choo via GitGitGadget <gitgitgadget@gmail.com>
Date
Jun 28, 2023, 19:26 UTC
Message-ID
<7b24eefbcf3e6b99134c50ff51a441b18ef7fd86.1687980393.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1497.v5.git.git.1687980390.gitgitgadget@gmail.com>
From: Glen Choo <chooglen@google.com>

Pass config_context when parsing CLI config. To provide the .kvi member, refactor out kvi_from_param() from the logic that caches CLI config in configsets. Now that config_context and config_context.kvi is always present when config machinery calls config callbacks, plumb "kvi" so that we can remove all calls of current_config_scope() except for trace2/*.c (which will be handled in a later commit), and remove all other current_config_*() (the functions themselves and their calls). Note that this results in .kvi containing a different, more complete set of information than the mocked up "struct config_source" in git_config_from_parameters().

Plumbing "kvi" reveals a few places where we've been doing the wrong thing:

* git_config_parse_parameter() hasn't been setting config source
  information, so plumb "kvi" there too.
* Several sites in builtin/config.c have been calling current_config_*()
  functions outside of config callbacks (indirectly, via the
  format_config() helper), which means they're reading state that isn't
  set correctly:
  * "git config --get-urlmatch --show-scope" iterates config to collect
    values, but then attempts to display the scope after config
    iteration, causing the "unknown" scope to be shown instead of the
    config file's scope. It's clear that this wasn't intended: we knew
    that "--get-urlmatch" couldn't show config source metadata, which is
    why "--show-origin" was marked incompatible with "--get-urlmatch"
    when it was introduced [1]. It was most likely a mistake that we
    allowed "--show-scope" to sneak through.
    Fix this by copying the "kvi" value in the collection phase so that
    it can be read back later. This means that we can now support "git
    config --get-urlmatch --show-origin", but that is left unchanged
    for now.
  * "git config --default" doesn't have config source metadata when
    displaying the default value, so "--show-scope" also results in
    "unknown", and "--show-origin" results in a BUG(). Fix this by
    treating the default value as if it came from the command line (e.g.
    like we do with "git -c" or "git config --file"), using
    kvi_from_param().
[1] https://lore.kernel.org/git/20160205112001.GA13397@sigill.intra.peff.net/
Signed-off-by: Glen Choo <chooglen@google.com>
---
 builtin/config.c  | 47 ++++++++++++++++++----------
 config.c          | 80 ++++++++++++++++++++++++-----------------------
 config.h          |  3 +-
 t/t1300-config.sh | 27 ++++++++++++++++
 4 files changed, 99 insertions(+), 58 deletions(-)
diff --git a/builtin/config.c b/builtin/config.c
index f4fccf99cb8..9b9f5527311 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -194,38 +194,42 @@ static void check_argc(int argc, int min, int max)
 	usage_builtin_config();
 }
 
-static void show_config_origin(struct strbuf *buf)
+static void show_config_origin(const struct key_value_info *kvi,
+			       struct strbuf *buf)
 {
 	const char term = end_nul ? '\0' : '\t';
 
-	strbuf_addstr(buf, current_config_origin_type());
+	strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
 	strbuf_addch(buf, ':');
 	if (end_nul)
-		strbuf_addstr(buf, current_config_name());
+		strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
 	else
-		quote_c_style(current_config_name(), buf, NULL, 0);
+		quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
 	strbuf_addch(buf, term);
 }
 
-static void show_config_scope(struct strbuf *buf)
+static void show_config_scope(const struct key_value_info *kvi,
+			      struct strbuf *buf)
 {
 	const char term = end_nul ? '\0' : '\t';
-	const char *scope = config_scope_name(current_config_scope());
+	const char *scope = config_scope_name(kvi->scope);
 
 	strbuf_addstr(buf, N_(scope));
 	strbuf_addch(buf, term);
 }
 
 static int show_all_config(const char *key_, const char *value_,
-			   const struct config_context *ctx UNUSED,
+			   const struct config_context *ctx,
 			   void *cb UNUSED)
 {
+	const struct key_value_info *kvi = ctx->kvi;
+
 	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
 		if (show_scope)
-			show_config_scope(&buf);
+			show_config_scope(kvi, &buf);
 		if (show_origin)
-			show_config_origin(&buf);
+			show_config_origin(kvi, &buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -243,12 +247,13 @@ struct strbuf_list {
 	int alloc;
 };
 
-static int format_config(struct strbuf *buf, const char *key_, const char *value_)
+static int format_config(struct strbuf *buf, const char *key_,
+			 const char *value_, const struct key_value_info *kvi)
 {
 	if (show_scope)
-		show_config_scope(buf);
+		show_config_scope(kvi, buf);
 	if (show_origin)
-		show_config_origin(buf);
+		show_config_origin(kvi, buf);
 	if (show_keys)
 		strbuf_addstr(buf, key_);
 	if (!omit_values) {
@@ -303,9 +308,10 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
 }
 
 static int collect_config(const char *key_, const char *value_,
-			  const struct config_context *ctx UNUSED, void *cb)
+			  const struct config_context *ctx, void *cb)
 {
 	struct strbuf_list *values = cb;
+	const struct key_value_info *kvi = ctx->kvi;
 
 	if (!use_key_regexp && strcmp(key_, key))
 		return 0;
@@ -320,7 +326,7 @@ static int collect_config(const char *key_, const char *value_,
 	ALLOC_GROW(values->items, values->nr + 1, values->alloc);
 	strbuf_init(&values->items[values->nr], 0);
 
-	return format_config(&values->items[values->nr++], key_, value_);
+	return format_config(&values->items[values->nr++], key_, value_, kvi);
 }
 
 static int get_value(const char *key_, const char *regex_, unsigned flags)
@@ -382,11 +388,14 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
 			    &config_options);
 
 	if (!values.nr && default_value) {
+		struct key_value_info kvi = KVI_INIT;
 		struct strbuf *item;
+
+		kvi_from_param(&kvi);
 		ALLOC_GROW(values.items, values.nr + 1, values.alloc);
 		item = &values.items[values.nr++];
 		strbuf_init(item, 0);
-		if (format_config(item, key_, default_value) < 0)
+		if (format_config(item, key_, default_value, &kvi) < 0)
 			die(_("failed to format default config value: %s"),
 				default_value);
 	}
@@ -563,15 +572,17 @@ static void check_write(void)
 struct urlmatch_current_candidate_value {
 	char value_is_null;
 	struct strbuf value;
+	struct key_value_info kvi;
 };
 
 static int urlmatch_collect_fn(const char *var, const char *value,
-			       const struct config_context *ctx UNUSED,
+			       const struct config_context *ctx,
 			       void *cb)
 {
 	struct string_list *values = cb;
 	struct string_list_item *item = string_list_insert(values, var);
 	struct urlmatch_current_candidate_value *matched = item->util;
+	const struct key_value_info *kvi = ctx->kvi;
 
 	if (!matched) {
 		matched = xmalloc(sizeof(*matched));
@@ -580,6 +591,7 @@ static int urlmatch_collect_fn(const char *var, const char *value,
 	} else {
 		strbuf_reset(&matched->value);
 	}
+	matched->kvi = *kvi;
 
 	if (value) {
 		strbuf_addstr(&matched->value, value);
@@ -627,7 +639,8 @@ static int get_urlmatch(const char *var, const char *url)
 		struct strbuf buf = STRBUF_INIT;
 
 		format_config(&buf, item->string,
-			      matched->value_is_null ? NULL : matched->value.buf);
+			      matched->value_is_null ? NULL : matched->value.buf,
+			      &matched->kvi);
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
 
diff --git a/config.c b/config.c
index 31718711827..4986942b091 100644
--- a/config.c
+++ b/config.c
@@ -219,7 +219,9 @@ static const char include_depth_advice[] = N_(
 "from\n"
 "	%s\n"
 "This might be due to circular includes.");
-static int handle_path_include(struct config_source *cs, const char *path,
+static int handle_path_include(struct config_source *cs,
+			       const struct key_value_info *kvi,
+			       const char *path,
 			       struct config_include_data *inc)
 {
 	int ret = 0;
@@ -260,8 +262,7 @@ static int handle_path_include(struct config_source *cs, const char *path,
 			    cs->name ? cs->name :
 			    "the command line");
 		ret = git_config_from_file_with_options(git_config_include, path, inc,
-							current_config_scope(),
-							NULL);
+							kvi->scope, NULL);
 		inc->depth--;
 	}
 cleanup:
@@ -510,7 +511,7 @@ static int git_config_include(const char *var, const char *value,
 		return ret;
 
 	if (!strcmp(var, "include.path"))
-		ret = handle_path_include(cs, value, inc);
+		ret = handle_path_include(cs, ctx->kvi, value, inc);
 
 	if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) &&
 	    cond && include_condition_is_true(cs, inc, cond, cond_len) &&
@@ -519,7 +520,7 @@ static int git_config_include(const char *var, const char *value,
 
 		if (inc->opts->unconditional_remote_url)
 			inc->fn = forbid_remote_url;
-		ret = handle_path_include(cs, value, inc);
+		ret = handle_path_include(cs, ctx->kvi, value, inc);
 		inc->fn = old_fn;
 	}
 
@@ -677,27 +678,44 @@ out_free_ret_1:
 }
 
 static int config_parse_pair(const char *key, const char *value,
-			  config_fn_t fn, void *data)
+			     struct key_value_info *kvi,
+			     config_fn_t fn, void *data)
 {
 	char *canonical_name;
 	int ret;
+	struct config_context ctx = {
+		.kvi = kvi,
+	};
 
 	if (!strlen(key))
 		return error(_("empty config key"));
 	if (git_config_parse_key(key, &canonical_name, NULL))
 		return -1;
 
-	ret = (fn(canonical_name, value, NULL, data) < 0) ? -1 : 0;
+	ret = (fn(canonical_name, value, &ctx, data) < 0) ? -1 : 0;
 	free(canonical_name);
 	return ret;
 }
 
+
+/* for values read from `git_config_from_parameters()` */
+void kvi_from_param(struct key_value_info *out)
+{
+	out->filename = NULL;
+	out->linenr = -1;
+	out->origin_type = CONFIG_ORIGIN_CMDLINE;
+	out->scope = CONFIG_SCOPE_COMMAND;
+}
+
 int git_config_parse_parameter(const char *text,
 			       config_fn_t fn, void *data)
 {
 	const char *value;
 	struct strbuf **pair;
 	int ret;
+	struct key_value_info kvi = KVI_INIT;
+
+	kvi_from_param(&kvi);
 
 	pair = strbuf_split_str(text, '=', 2);
 	if (!pair[0])
@@ -716,12 +734,13 @@ int git_config_parse_parameter(const char *text,
 		return error(_("bogus config parameter: %s"), text);
 	}
 
-	ret = config_parse_pair(pair[0]->buf, value, fn, data);
+	ret = config_parse_pair(pair[0]->buf, value, &kvi, fn, data);
 	strbuf_list_free(pair);
 	return ret;
 }
 
-static int parse_config_env_list(char *env, config_fn_t fn, void *data)
+static int parse_config_env_list(char *env, struct key_value_info *kvi,
+				 config_fn_t fn, void *data)
 {
 	char *cur = env;
 	while (cur && *cur) {
@@ -755,7 +774,7 @@ static int parse_config_env_list(char *env, config_fn_t fn, void *data)
 					     CONFIG_DATA_ENVIRONMENT);
 			}
 
-			if (config_parse_pair(key, value, fn, data) < 0)
+			if (config_parse_pair(key, value, kvi, fn, data) < 0)
 				return -1;
 		}
 		else {
@@ -780,10 +799,13 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 	int ret = 0;
 	char *envw = NULL;
 	struct config_source source = CONFIG_SOURCE_INIT;
+	struct key_value_info kvi = KVI_INIT;
 
 	source.origin_type = CONFIG_ORIGIN_CMDLINE;
 	config_reader_push_source(&the_reader, &source);
 
+	kvi_from_param(&kvi);
+
 	env = getenv(CONFIG_COUNT_ENVIRONMENT);
 	if (env) {
 		unsigned long count;
@@ -819,7 +841,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 			}
 			strbuf_reset(&envvar);
 
-			if (config_parse_pair(key, value, fn, data) < 0) {
+			if (config_parse_pair(key, value, &kvi, fn, data) < 0) {
 				ret = -1;
 				goto out;
 			}
@@ -830,7 +852,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 	if (env) {
 		/* sq_dequote will write over it */
 		envw = xstrdup(env);
-		if (parse_config_env_list(envw, fn, data) < 0) {
+		if (parse_config_env_list(envw, &kvi, fn, data) < 0) {
 			ret = -1;
 			goto out;
 		}
@@ -2442,7 +2464,8 @@ static int configset_find_element(struct config_set *set, const char *key,
 	return 0;
 }
 
-static int configset_add_value(struct config_reader *reader,
+static int configset_add_value(const struct key_value_info *kvi_p,
+			       struct config_reader *reader,
 			       struct config_set *set, const char *key,
 			       const char *value)
 {
@@ -2476,13 +2499,9 @@ static int configset_add_value(struct config_reader *reader,
 	if (!reader->source)
 		BUG("configset_add_value has no source");
 	if (reader->source->name) {
-		kvi_from_source(reader->source, current_config_scope(), kv_info);
+		kvi_from_source(reader->source, kvi_p->scope, kv_info);
 	} else {
-		/* for values read from `git_config_from_parameters()` */
-		kv_info->filename = NULL;
-		kv_info->linenr = -1;
-		kv_info->origin_type = CONFIG_ORIGIN_CMDLINE;
-		kv_info->scope = reader->parsing_scope;
+		kvi_from_param(kv_info);
 	}
 	si->util = kv_info;
 
@@ -2538,11 +2557,12 @@ struct configset_add_data {
 #define CONFIGSET_ADD_INIT { 0 }
 
 static int config_set_callback(const char *key, const char *value,
-			       const struct config_context *ctx UNUSED,
+			       const struct config_context *ctx,
 			       void *cb)
 {
 	struct configset_add_data *data = cb;
-	configset_add_value(data->config_reader, data->config_set, key, value);
+	configset_add_value(ctx->kvi, data->config_reader, data->config_set,
+			    key, value);
 	return 0;
 }
 
@@ -4037,16 +4057,6 @@ const char *config_origin_type_name(enum config_origin_type type)
 	}
 }
 
-const char *current_config_origin_type(void)
-{
-	enum config_origin_type type = CONFIG_ORIGIN_UNKNOWN;
-
-	if (reader_origin_type(&the_reader, &type))
-		BUG("current_config_origin_type called outside config callback");
-
-	return config_origin_type_name(type);
-}
-
 const char *config_scope_name(enum config_scope scope)
 {
 	switch (scope) {
@@ -4078,14 +4088,6 @@ static int reader_config_name(struct config_reader *reader, const char **out)
 	return 0;
 }
 
-const char *current_config_name(void)
-{
-	const char *name;
-	if (reader_config_name(&the_reader, &name))
-		BUG("current_config_name called outside config callback");
-	return name ? name : "";
-}
-
 enum config_scope current_config_scope(void)
 {
 	if (the_reader.config_kvi)
diff --git a/config.h b/config.h
index 206bf1f175a..ea92392400e 100644
--- a/config.h
+++ b/config.h
@@ -387,9 +387,8 @@ void git_global_config(char **user, char **xdg);
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
 enum config_scope current_config_scope(void);
-const char *current_config_origin_type(void);
-const char *current_config_name(void);
 const char *config_origin_type_name(enum config_origin_type type);
+void kvi_from_param(struct key_value_info *out);
 
 /*
  * Match and parse a config key of the form:
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 86bfbc2b364..387d336c91f 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1668,6 +1668,21 @@ test_expect_success 'urlmatch' '
 	test_cmp expect actual
 '
 
+test_expect_success 'urlmatch with --show-scope' '
+	cat >.git/config <<-\EOF &&
+	[http "https://weak.example.com"]
+		sslVerify = false
+		cookieFile = /tmp/cookie.txt
+	EOF
+
+	cat >expect <<-EOF &&
+	local	http.cookiefile /tmp/cookie.txt
+	local	http.sslverify false
+	EOF
+	git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'urlmatch favors more specific URLs' '
 	cat >.git/config <<-\EOF &&
 	[http "https://example.com/"]
@@ -2055,6 +2070,12 @@ test_expect_success '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-origin with --default' '
+	git config --show-origin --default foo some.key >actual &&
+	echo "command line:	foo" >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success '--show-scope with --list' '
 	cat >expect <<-EOF &&
 	global	user.global=true
@@ -2123,6 +2144,12 @@ test_expect_success '--show-scope with --show-origin' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --default' '
+	git config --show-scope --default foo some.key >actual &&
+	echo "command	foo" >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'override global and system config' '
 	test_when_finished rm -f \"\$HOME\"/.gitconfig &&
 	cat >"$HOME"/.gitconfig <<-EOF &&
-- 
gitgitgadget
Previous: Glen Choo via GitGitGadgetNext: Glen Choo via GitGitGadget
Message 106 of 115 in “[RFC] config: remove global state from config iteration”
  1. 00/14 [RFC] config: remove global state from config iterationGlen Choo via GitGitGadget, Apr 21, 2023
  2. 01/14 config.c: introduce kvi_fn(), use it for configsetsGlen Choo via GitGitGadget, Apr 21, 2023
  3. 02/14 config.c: use kvi for CLI configGlen Choo via GitGitGadget, Apr 21, 2023
  4. Ævar Arnfjörð BjarmasonMay 1, 2023
  5. 06/14 config: inline git_color_default_configGlen Choo via GitGitGadget, Apr 21, 2023
  6. 03/14 config: use kvi for config filesGlen Choo via GitGitGadget, Apr 21, 2023
  7. 04/14 config: add kvi.path, use it to evaluate includesGlen Choo via GitGitGadget, Apr 21, 2023
  8. 05/14 config: pass source to config_parser_event_fn_tGlen Choo via GitGitGadget, Apr 21, 2023
  9. 07/14 urlmatch.h: use config_fn_t typeGlen Choo via GitGitGadget, Apr 21, 2023
  10. 08/14 (RFC-only) config: add kvi arg to config_fn_tGlen Choo via GitGitGadget, Apr 21, 2023
  11. 10/14 (RFC-only) config: finish config_fn_t refactorGlen Choo via GitGitGadget, Apr 21, 2023
  12. Ævar Arnfjörð BjarmasonMay 1, 2023
  13. Jonathan TanMay 5, 2023
  14. Glen ChooMay 9, 2023
  15. Jonathan TanMay 11, 2023
  16. Glen ChooMay 8, 2023
  17. 11/14 config: remove current_config_(line|name|origin_type)Glen Choo via GitGitGadget, Apr 21, 2023
  18. 14/14 config: remove config_reader from configset_add_valueGlen Choo via GitGitGadget, Apr 21, 2023
  19. 12/14 config: remove current_config_scope()Glen Choo via GitGitGadget, Apr 21, 2023
  20. 09/14 (RFC-only) config: apply cocci to config_fn_t implementationsGlen Choo via GitGitGadget, Apr 21, 2023
  21. 13/14 config: pass kvi to die_bad_number()Glen Choo via GitGitGadget, Apr 21, 2023
  22. 00/14 [RFC] config: remove global state from config iterationGlen Choo via GitGitGadget, May 30, 2023
  23. 01/14 config: inline git_color_default_configGlen Choo via GitGitGadget, May 30, 2023
  24. 02/14 urlmatch.h: use config_fn_t typeGlen Choo via GitGitGadget, May 30, 2023
  25. 03/14 (RFC-only) config: add kvi arg to config_fn_tGlen Choo via GitGitGadget, May 30, 2023
  26. Phillip WoodJun 1, 2023
  27. Glen ChooJun 1, 2023
  28. Phillip WoodJun 2, 2023
  29. Glen ChooJun 2, 2023
  30. Phillip WoodJun 5, 2023
  31. Glen ChooJun 9, 2023
  32. 08/14 builtin/config.c: test misuse of format_config()Glen Choo via GitGitGadget, May 30, 2023
  33. 06/14 config.c: pass kvi in configsetsGlen Choo via GitGitGadget, May 30, 2023
  34. Jonathan TanJun 1, 2023
  35. 05/14 (RFC-only) config: finish config_fn_t refactorGlen Choo via GitGitGadget, May 30, 2023
  36. Jonathan TanJun 1, 2023
  37. 07/14 config: provide kvi with config filesGlen Choo via GitGitGadget, May 30, 2023
  38. Jonathan TanJun 1, 2023
  39. Jonathan TanJun 1, 2023
  40. 04/14 (RFC-only) config: apply cocci to config_fn_t implementationsGlen Choo via GitGitGadget, May 30, 2023
  41. 09/14 config.c: provide kvi with CLI configGlen Choo via GitGitGadget, May 30, 2023
  42. Jonathan TanJun 1, 2023
  43. Glen ChooJun 2, 2023
  44. 10/14 trace2: plumb config kviGlen Choo via GitGitGadget, May 30, 2023
  45. Jonathan TanJun 1, 2023
  46. 12/14 config.c: remove config_reader from configsetsGlen Choo via GitGitGadget, May 30, 2023
  47. 13/14 config: add kvi.path, use it to evaluate includesGlen Choo via GitGitGadget, May 30, 2023
  48. Jonathan TanJun 2, 2023
  49. 14/14 config: pass source to config_parser_event_fn_tGlen Choo via GitGitGadget, May 30, 2023
  50. Jonathan TanJun 2, 2023
  51. Glen ChooJun 2, 2023
  52. 11/14 config: pass kvi to die_bad_number()Glen Choo via GitGitGadget, May 30, 2023
  53. Jonathan TanJun 1, 2023
  54. Glen ChooJun 2, 2023
  55. 00/12 config: remove global state from config iterationGlen Choo via GitGitGadget, Jun 20, 2023
  56. 02/12 urlmatch.h: use config_fn_t typeGlen Choo via GitGitGadget, Jun 20, 2023
  57. Junio C HamanoJun 20, 2023
  58. 01/12 config: inline git_color_default_configGlen Choo via GitGitGadget, Jun 20, 2023
  59. Junio C HamanoJun 20, 2023
  60. 04/12 config.c: pass ctx in configsetsGlen Choo via GitGitGadget, Jun 20, 2023
  61. Junio C HamanoJun 20, 2023
  62. 05/12 config: pass ctx with config filesGlen Choo via GitGitGadget, Jun 20, 2023
  63. 06/12 builtin/config.c: test misuse of format_config()Glen Choo via GitGitGadget, Jun 20, 2023
  64. Junio C HamanoJun 20, 2023
  65. Glen ChooJun 20, 2023
  66. Jonathan TanJun 23, 2023
  67. Jeff KingJun 24, 2023
  68. Glen ChooJun 28, 2023
  69. 07/12 config.c: pass ctx with CLI configGlen Choo via GitGitGadget, Jun 20, 2023
  70. Jonathan TanJun 23, 2023
  71. Glen ChooJun 23, 2023
  72. 08/12 trace2: plumb config kviGlen Choo via GitGitGadget, Jun 20, 2023
  73. Jonathan TanJun 23, 2023
  74. 10/12 config.c: remove config_reader from configsetsGlen Choo via GitGitGadget, Jun 20, 2023
  75. Jonathan TanJun 23, 2023
  76. Junio C HamanoJun 23, 2023
  77. 03/12 config: add ctx arg to config_fn_tGlen Choo via GitGitGadget, Jun 20, 2023
  78. 11/12 config: add kvi.path, use it to evaluate includesGlen Choo via GitGitGadget, Jun 20, 2023
  79. 12/12 config: pass source to config_parser_event_fn_tGlen Choo via GitGitGadget, Jun 20, 2023
  80. Junio C HamanoJun 20, 2023
  81. 09/12 config: pass kvi to die_bad_number()Glen Choo via GitGitGadget, Jun 20, 2023
  82. Junio C HamanoJun 21, 2023
  83. Glen ChooJun 21, 2023
  84. Jonathan TanJun 23, 2023
  85. Junio C HamanoJun 23, 2023
  86. Glen ChooJun 23, 2023
  87. 00/12 config: remove global state from config iterationGlen Choo via GitGitGadget, Jun 26, 2023
  88. 01/12 config: inline git_color_default_configGlen Choo via GitGitGadget, Jun 26, 2023
  89. 02/12 urlmatch.h: use config_fn_t typeGlen Choo via GitGitGadget, Jun 26, 2023
  90. 04/12 config.c: pass ctx in configsetsGlen Choo via GitGitGadget, Jun 26, 2023
  91. 06/12 builtin/config.c: test misuse of format_config()Glen Choo via GitGitGadget, Jun 26, 2023
  92. 05/12 config: pass ctx with config filesGlen Choo via GitGitGadget, Jun 26, 2023
  93. 07/12 config.c: pass ctx with CLI configGlen Choo via GitGitGadget, Jun 26, 2023
  94. 08/12 trace2: plumb config kviGlen Choo via GitGitGadget, Jun 26, 2023
  95. 03/12 config: add ctx arg to config_fn_tGlen Choo via GitGitGadget, Jun 26, 2023
  96. 11/12 config: add kvi.path, use it to evaluate includesGlen Choo via GitGitGadget, Jun 26, 2023
  97. 12/12 config: pass source to config_parser_event_fn_tGlen Choo via GitGitGadget, Jun 26, 2023
  98. 10/12 config.c: remove config_reader from configsetsGlen Choo via GitGitGadget, Jun 26, 2023
  99. 09/12 config: pass kvi to die_bad_number()Glen Choo via GitGitGadget, Jun 26, 2023
  100. Junio C HamanoJun 26, 2023
  101. 00/11 config: remove global state from config iterationGlen Choo via GitGitGadget, Jun 28, 2023
  102. 01/11 config: inline git_color_default_configGlen Choo via GitGitGadget, Jun 28, 2023
  103. 02/11 urlmatch.h: use config_fn_t typeGlen Choo via GitGitGadget, Jun 28, 2023
  104. 04/11 config.c: pass ctx in configsetsGlen Choo via GitGitGadget, Jun 28, 2023
  105. 05/11 config: pass ctx with config filesGlen Choo via GitGitGadget, Jun 28, 2023
  106. 06/11 config.c: pass ctx with CLI configGlen Choo via GitGitGadget, Jun 28, 2023
  107. 07/11 trace2: plumb config kviGlen Choo via GitGitGadget, Jun 28, 2023
  108. 03/11 config: add ctx arg to config_fn_tGlen Choo via GitGitGadget, Jun 28, 2023
  109. 09/11 config.c: remove config_reader from configsetsGlen Choo via GitGitGadget, Jun 28, 2023
  110. 10/11 config: add kvi.path, use it to evaluate includesGlen Choo via GitGitGadget, Jun 28, 2023
  111. 11/11 config: pass source to config_parser_event_fn_tGlen Choo via GitGitGadget, Jun 28, 2023
  112. 08/11 config: pass kvi to die_bad_number()Glen Choo via GitGitGadget, Jun 28, 2023
  113. Jonathan TanJun 28, 2023
  114. Junio C HamanoJun 28, 2023
  115. Phillip WoodJul 11, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.