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

[PATCH 3/3] config: Add --null/-z option for null-delimted output

From
Frank Lichtenheld <frank@lichtenheld.de>
Date
Jun 25, 2007, 14:03 UTC
Message-ID
<11827802382221-git-send-email-frank@lichtenheld.de>
In-Reply-To
<200706220156.01175.jnareb@gmail.com>

Use \n as delimiter between key and value and \0 as delimiter after each key/value pair. This should be easily parsable output.

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de>
---
 Documentation/git-config.txt |   18 +++++++++++++-----
 builtin-config.c             |   20 ++++++++++++++------
 t/t1300-repo-config.sh       |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 11 deletions(-)
 This time with documentation and test cases.
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index bb6dbb0..8c09b88 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,17 +9,17 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git-config' [--system | --global] name [value [value_regex]]
+'git-config' [--system | --global] [-z|--null] name [value [value_regex]]
 'git-config' [--system | --global] --add name value
 'git-config' [--system | --global] --replace-all name [value [value_regex]]
-'git-config' [--system | --global] [type] --get name [value_regex]
-'git-config' [--system | --global] [type] --get-all name [value_regex]
-'git-config' [--system | --global] [type] --get-regexp name_regex [value_regex]
+'git-config' [--system | --global] [type] [-z|--null] --get name [value_regex]
+'git-config' [--system | --global] [type] [-z|--null] --get-all name [value_regex]
+'git-config' [--system | --global] [type] [-z|--null] --get-regexp name_regex [value_regex]
 'git-config' [--system | --global] --unset name [value_regex]
 'git-config' [--system | --global] --unset-all name [value_regex]
 'git-config' [--system | --global] --rename-section old_name new_name
 'git-config' [--system | --global] --remove-section name
-'git-config' [--system | --global] -l | --list
+'git-config' [--system | --global] [-z|--null] -l | --list
 
 DESCRIPTION
 -----------
@@ -118,6 +118,14 @@ See also <<FILES>>.
 	in the config file will cause the value to be multiplied
 	by 1024, 1048576, or 1073741824 prior to output.
 
+-z, --null::
+	For all options that output values and/or keys, always
+	end values with with the null character (instead of a
+	newline). Use newline instead as a delimiter between
+	key and value. This allows for secure parsing of the
+	output without getting confused e.g. by values that
+	contain line breaks. 
+
 
 [[FILES]]
 FILES
diff --git a/builtin-config.c b/builtin-config.c
index dbc2339..9d52ba8 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -2,7 +2,7 @@
 #include "cache.h"
 
 static const char git_config_set_usage[] =
-"git-config [ --global | --system ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list";
+"git-config [ --global | --system ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list";
 
 static char *key;
 static regex_t *key_regexp;
@@ -12,14 +12,17 @@ static int use_key_regexp;
 static int do_all;
 static int do_not_match;
 static int seen;
+static char delim = '=';
+static char key_delim = ' ';
+static char term = '\n';
 static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
 
 static int show_all_config(const char *key_, const char *value_)
 {
 	if (value_)
-		printf("%s=%s\n", key_, value_);
+		printf("%s%c%s%c", key_, delim, value_, term);
 	else
-		printf("%s\n", key_);
+		printf("%s%c", key_, term);
 	return 0;
 }
 
@@ -40,9 +43,9 @@ static int show_config(const char* key_, const char* value_)
 
 	if (show_keys) {
 		if (value_)
-			printf("%s ", key_);
+			printf("%s%c", key_, key_delim);
 		else
-			printf("%s", key_);
+			printf("%s",key_);
 	}
 	if (seen && !do_all)
 		dup_error = 1;
@@ -58,7 +61,7 @@ static int show_config(const char* key_, const char* value_)
 				key_, vptr);
 	}
 	else
-		printf("%s\n", vptr);
+		printf("%s%c", vptr, term);
 
 	return 0;
 }
@@ -159,6 +162,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		}
 		else if (!strcmp(argv[1], "--system"))
 			setenv("GIT_CONFIG", ETC_GITCONFIG, 1);
+		else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) {
+			term = '\0';
+			delim = '\n';
+			key_delim = '\n';
+		}
 		else if (!strcmp(argv[1], "--rename-section")) {
 			int ret;
 			if (argc != 4)
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 8b5e9fc..99d84cc 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -519,4 +519,36 @@ git config --list > result
 
 test_expect_success 'value continued on next line' 'cmp result expect'
 
+cat > .git/config <<\EOF
+[section "sub=section"]
+	val1 = foo=bar
+	val2 = foo\nbar
+	val3 = \n\n
+	val4 =
+	val5
+EOF
+
+cat > expect <<\EOF
+Key: section.sub=section.val1
+Value: foo=bar
+Key: section.sub=section.val2
+Value: foo
+bar
+Key: section.sub=section.val3
+Value: 
+
+
+Key: section.sub=section.val4
+Value: 
+Key: section.sub=section.val5
+EOF
+
+git config --null --list | perl -0ne 'chop;($key,$value)=split(/\n/,$_,2);print "Key: $key\n";print "Value: $value\n" if defined($value)' > result
+
+test_expect_success '--null --list' 'cmp result expect'
+
+git config --null --get-regexp 'val[0-9]' | perl -0ne 'chop;($key,$value)=split(/\n/,$_,2);print "Key: $key\n";print "Value: $value\n" if defined($value)' > result
+
+test_expect_success '--null --get-regexp' 'cmp result expect'
+
 test_done
-- 
1.5.2.1
Previous: Junio C HamanoNext: Jakub Narebski
Message 31 of 34 in “[RFC] Implementing git config handling in Git.pm”
  1. Frank LichtenheldMay 20, 2007
  2. Petr BaudisMay 20, 2007
  3. config: Add --quoted option to produce machine-parsable outputFrank Lichtenheld, May 21, 2007
  4. Junio C HamanoMay 21, 2007
  5. Johannes SchindelinMay 21, 2007
  6. Junio C HamanoMay 21, 2007
  7. Johannes SchindelinMay 21, 2007
  8. Jan HudecMay 21, 2007
  9. Frank LichtenheldMay 21, 2007
  10. Jakub NarebskiMay 21, 2007
  11. config: Add --null/-z option for null-delimted outputFrank Lichtenheld, Jun 17, 2007
  12. Johannes SchindelinJun 19, 2007
  13. Jakub NarebskiJun 19, 2007
  14. Frank LichtenheldJun 19, 2007
  15. Johannes SchindelinJun 19, 2007
  16. Junio C HamanoJun 19, 2007
  17. Frank LichtenheldJun 19, 2007
  18. Johannes SchindelinJun 19, 2007
  19. David KastrupJun 19, 2007
  20. Jakub NarebskiJun 19, 2007
  21. Frank LichtenheldJun 19, 2007
  22. Johannes SchindelinJun 19, 2007
  23. Frank LichtenheldJun 19, 2007
  24. Johannes SchindelinJun 20, 2007
  25. Jakub NarebskiJun 20, 2007
  26. Jakub NarebskiJun 21, 2007
  27. Frank LichtenheldJun 22, 2007
  28. 1/3 config: Complete documentation of --get-regexpFrank Lichtenheld, Jun 25, 2007
  29. 2/3 config: Change output of --get-regexp for valueless keysFrank Lichtenheld, Jun 25, 2007
  30. Junio C HamanoJun 27, 2007
  31. 3/3 config: Add --null/-z option for null-delimted outputFrank Lichtenheld, Jun 25, 2007
  32. Jakub NarebskiJun 25, 2007
  33. Frank LichtenheldJun 26, 2007
  34. Junio C HamanoJun 27, 2007

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.