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

[PATCH 4/5] config.c: add a "tristate" helper

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Apr 8, 2021, 13:34 UTC
Message-ID
<patch-4.6-222e91e11b-20210408T133125Z-avarab@gmail.com>
In-Reply-To
<cover-0.6-0000000000-20210408T133125Z-avarab@gmail.com>

Add "tristate" functions to go along with the "bool" functions and migrate the common pattern of checking if something is "bool" or "auto" in various places over to the new functions.

We also have e.g. "repo_config_get_bool" and "config_error_nonbool". I'm not adding corresponding "tristate" functions as they're not needed by anything, but we could add those in the future if they are.

I'm not migrating over "core.abbrev" parsing as part of this change. When "core.abbrev" was made optionally boolean in a9ecaa06a7 (core.abbrev=no disables abbreviations, 2020-09-01) the "die if empty" code added in g48d5014dd4 (config.abbrev: document the new default that auto-scales, 2016-11-01) wasn't adjusted. It thus behaves unlike all other "maybe bool" config variables.

I have a planned series to start adding some tests for "core.abbrev", but AFAICT there's not even a test for "core.abbrev=true", and I'd like to focus on thing that have no behavior change here, so let's leave it for now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/log.c  | 13 +++++++------
 compat/mingw.c |  6 +++---
 config.c       | 16 ++++++++++++++++
 config.h       | 12 ++++++++++++
 http.c         |  5 +++--
 userdiff.c     |  6 ++----
 6 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/builtin/log.c b/builtin/log.c
index 8acd285daf..0d945313d8 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -868,11 +868,12 @@ static int git_format_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 	if (!strcmp(var, "format.numbered")) {
-		if (value && !strcasecmp(value, "auto")) {
+		int tristate = git_config_tristate(var, value);
+		if (tristate == 2) {
 			auto_number = 1;
 			return 0;
 		}
-		numbered = git_config_bool(var, value);
+		numbered = tristate;
 		auto_number = auto_number && numbered;
 		return 0;
 	}
@@ -904,11 +905,11 @@ static int git_format_config(const char *var, const char *value, void *cb)
 	if (!strcmp(var, "format.signaturefile"))
 		return git_config_pathname(&signature_file, var, value);
 	if (!strcmp(var, "format.coverletter")) {
-		if (value && !strcasecmp(value, "auto")) {
+		int tristate = git_config_tristate(var, value);
+		if (tristate == 2)
 			config_cover_letter = COVER_AUTO;
-			return 0;
-		}
-		config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
+		else
+			config_cover_letter = tristate ? COVER_ON : COVER_OFF;
 		return 0;
 	}
 	if (!strcmp(var, "format.outputdirectory"))
diff --git a/compat/mingw.c b/compat/mingw.c
index a43599841c..e6e85ae99a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -247,11 +247,11 @@ int mingw_core_config(const char *var, const char *value, void *cb)
 	}
 
 	if (!strcmp(var, "core.restrictinheritedhandles")) {
-		if (value && !strcasecmp(value, "auto"))
+		int tristate = git_config_tristate(var, value);
+		if (tristate == 2)
 			core_restrict_inherited_handles = -1;
 		else
-			core_restrict_inherited_handles =
-				git_config_bool(var, value);
+			core_restrict_inherited_handles = tristate;
 		return 0;
 	}
 
diff --git a/config.c b/config.c
index fc28dbd97c..74d2b2c0df 100644
--- a/config.c
+++ b/config.c
@@ -1257,6 +1257,14 @@ int git_parse_maybe_bool(const char *value)
 	return -1;
 }
 
+int git_parse_maybe_tristate(const char *value)
+{
+	int v = git_parse_maybe_bool(value);
+	if (v < 0 && !strcasecmp(value, "auto"))
+		return 2;
+	return v;
+}
+
 int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
 {
 	int v = git_parse_maybe_bool_text(value);
@@ -1268,6 +1276,14 @@ int git_config_bool_or_int(const char *name, const char *value, int *is_bool)
 	return git_config_int(name, value);
 }
 
+int git_config_tristate(const char *name, const char *value)
+{
+	int v = git_parse_maybe_tristate(value);
+	if (v < 0)
+		die(_("bad tristate config value '%s' for '%s'"), value, name);
+	return v;
+}
+
 int git_config_bool(const char *name, const char *value)
 {
 	int v = git_parse_maybe_bool(value);
diff --git a/config.h b/config.h
index 19a9adbaa9..c5129e4392 100644
--- a/config.h
+++ b/config.h
@@ -197,6 +197,12 @@ int git_parse_ulong(const char *, unsigned long *);
  */
 int git_parse_maybe_bool(const char *);
 
+/**
+ * Same as `git_parse_maybe_bool`, except that "auto" is recognized and
+ * will return "2".
+ */
+int git_parse_maybe_tristate(const char *);
+
 /**
  * Parse the string to an integer, including unit factors. Dies on error;
  * otherwise, returns the parsed result.
@@ -226,6 +232,12 @@ int git_config_bool_or_int(const char *, const char *, int *);
  */
 int git_config_bool(const char *, const char *);
 
+/**
+ * Like git_config_bool() except "auto" is also recognized and will
+ * return "2"
+ */
+int git_config_tristate(const char *, const char *);
+
 /**
  * Allocates and copies the value string into the `dest` parameter; if no
  * string is given, prints an error message and returns -1.
diff --git a/http.c b/http.c
index 406410f884..b54a232e90 100644
--- a/http.c
+++ b/http.c
@@ -406,10 +406,11 @@ static int http_options(const char *var, const char *value, void *cb)
 		return git_config_string(&user_agent, var, value);
 
 	if (!strcmp("http.emptyauth", var)) {
-		if (value && !strcmp("auto", value))
+		int tristate = git_config_tristate(var, value);
+		if (tristate == 2)
 			curl_empty_auth = -1;
 		else
-			curl_empty_auth = git_config_bool(var, value);
+			curl_empty_auth = tristate;
 		return 0;
 	}
 
diff --git a/userdiff.c b/userdiff.c
index 3f81a2261c..7ff010961f 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -277,10 +277,8 @@ static int parse_funcname(struct userdiff_funcname *f, const char *k,
 
 static int parse_tristate(int *b, const char *k, const char *v)
 {
-	if (v && !strcasecmp(v, "auto"))
-		*b = -1;
-	else
-		*b = git_config_bool(k, v);
+	int tristate = git_config_tristate(k, v);
+	*b = tristate == 2 ? -1 : tristate;
 	return 0;
 }
 
-- 
2.31.1.527.g9b8f7de2547
Previous: Junio C HamanoNext: Junio C Hamano
Message 9 of 21 in “config: support --type=bool-or-auto for "tristate" parsing”
  1. 0/5 config: support --type=bool-or-auto for "tristate" parsingÆvar Arnfjörð Bjarmason, Apr 8, 2021
  2. 1/5 config.c: add a comment about why value=NULL is trueÆvar Arnfjörð Bjarmason, Apr 8, 2021
  3. Junio C HamanoApr 8, 2021
  4. 2/5 config tests: test for --bool-or-strÆvar Arnfjörð Bjarmason, Apr 8, 2021
  5. Junio C HamanoApr 8, 2021
  6. Ævar Arnfjörð BjarmasonApr 8, 2021
  7. 3/5 git-config: document --bool-or-str and --type=bool-or-strÆvar Arnfjörð Bjarmason, Apr 8, 2021
  8. Junio C HamanoApr 8, 2021
  9. 4/5 config.c: add a "tristate" helperÆvar Arnfjörð Bjarmason, Apr 8, 2021
  10. Junio C HamanoApr 8, 2021
  11. Ævar Arnfjörð BjarmasonApr 8, 2021
  12. Junio C HamanoApr 8, 2021
  13. Ævar Arnfjörð BjarmasonApr 9, 2021
  14. Junio C HamanoApr 9, 2021
  15. Junio C HamanoApr 8, 2021
  16. Jeff KingApr 9, 2021
  17. Junio C HamanoApr 9, 2021
  18. Jeff KingApr 10, 2021
  19. Junio C HamanoApr 10, 2021
  20. 5/5 config: add --type=bool-or-auto switchÆvar Arnfjörð Bjarmason, Apr 8, 2021
  21. Junio C HamanoApr 8, 2021

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.