Thread (97 messages) 97 messages, 9 authors, 2025-08-03

RE: [PATCH v4 07/14] builtin/config: introduce "list" subcommand

From: <hidden>
Date: 2024-05-03 13:16:50

On Friday, May 3, 2024 9:09 AM. Karthik Nayak wrote:
Patrick Steinhardt [off-list ref] writes:
quoted
While git-config(1) has several modes, those modes are not exposed
with subcommands but instead by specifying e.g. `--unset` or `--list`.
This
s/specifying/specifying flags/ perhaps?
quoted
user interface is not really in line with how our more modern commands
work, where it is a lot more customary to say e.g. `git remote list`.
Tangent: I totally agree with the patch, but it would be nice to have a
'DesigningCommands' document which would highlight UX do's and don'ts.
It would be nice to add that as reference in discussions.
quoted
Furthermore, to add to the confusion, git-config(1) also allows the
user to request modes implicitly by just specifying the correct number
of arguments. Thus, `git config foo.bar` will retrieve the value of
"foo.bar" while `git config foo.bar baz` will set it to "baz".

Overall, this makes for a confusing interface that could really use a
makeover. It hurts discoverability of what you can do with
git-config(1) and is comparatively easy to get wrong. Converting the
command to have subcommands instead would go a long way to help address
these issues.
quoted
One concern in this context is backwards compatibility. Luckily, we
can introduce subcommands without breaking backwards compatibility at all.
This is because all the implicit modes of git-config(1) require that
the first argument is a properly formatted config key. And as config
keys _must_ have a dot in their name, any value without a dot would
have been discarded by git-config(1) previous to this change. Thus,
given that none of the subcommands do have a dot, they are unambiguous.

Introduce the first such new subcommand, which is "git config list".
To retain backwards compatibility we only conditionally use
subcommands and will fall back to the old syntax in case no subcommand was
detected.
quoted
This should help to transition to the new-style syntax until we
eventually deprecate and remove the old-style syntax.

Note that the way we handle this we're duplicating some functionality
across old and new syntax. While this isn't pretty, it helps us to
ensure that there really is no change in behaviour for the old syntax.

Amend tests such that we run them both with old and new style syntax.
As tests are now run twice, state from the first run may be still be
around in the second run and thus cause tests to fail. Add cleanup
logic as required to fix such tests.

Signed-off-by: Patrick Steinhardt <redacted>
---
 Documentation/git-config.txt |  26 ++++++---
 builtin/config.c             |  90 ++++++++++++++++++++++++----
 t/t1300-config.sh            | 110 +++++++++++++++++++++--------------
 3 files changed, 162 insertions(+), 64 deletions(-)
diff --git a/Documentation/git-config.txt
b/Documentation/git-config.txt index ac61113fcc..c83c97cb7e 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,6 +9,7 @@ git-config - Get and set repository or global options
SYNOPSIS
 --------
 [verse]
+'git config list' [<file-option>] [<display-option>] [--includes]
 'git config' [<file-option>] [--type=<type>] [--comment=<message>]
[--fixed-value] [--show-origin] [--show-scope] [-z|--null] <name>
[<value> [<value-pattern>]]  'git config' [<file-option>]
[--type=<type>] [--comment=<message>] --add <name> <value>  'git
config' [<file-option>] [--type=<type>] [--comment=<message>]
[--fixed-value] --replace-all <name> <value> [<value-pattern>] @@
-20,7 +21,6 @@ SYNOPSIS  'git config' [<file-option>] [--fixed-value]
--unset-all <name> [<value-pattern>]  'git config' [<file-option>]
--rename-section <old-name> <new-name>  'git config' [<file-option>]
--remove-section <name> -'git config' [<file-option>] [--show-origin]
[--show-scope] [-z|--null] [--name-only] -l | --list  'git config'
[<file-option>] --get-color <name> [<default>]  'git config' [<file-option>] --get-
colorbool <name> [<stdout-is-tty>]  'git config' [<file-option>] -e | --edit @@ -74,6
+74,12 @@ On success, the command returns the exit code 0.
quoted
 A list of all available configuration variables can be obtained using
the  `git help --config` command.

+COMMANDS
+--------
+
+list::
+	List all variables set in config file, along with their values.
+
 [[OPTIONS]]
 OPTIONS
 -------
@@ -190,10 +196,6 @@ See also <<FILES>>.
 --unset-all::
 	Remove all lines matching the key from config file.

--l::
---list::
-	List all variables set in config file, along with their values.
-
 --fixed-value::
 	When used with the `value-pattern` argument, treat `value-pattern` as
 	an exact string instead of a regular expression. This will restrict
@@ -248,7 +250,7 @@ Valid `<type>`'s include:
 	contain line breaks.

 --name-only::
-	Output only the names of config variables for `--list` or
+	Output only the names of config variables for `list` or
 	`--get-regexp`.

 --show-origin::
@@ -300,10 +302,20 @@ Valid `<type>`'s include:
   When using `--get`, and the requested variable is not found, behave as if
   <value> were the value assigned to that variable.

+DEPRECATED MODES
+----------------
+
+The following modes have been deprecated in favor of subcommands. It
+is recommended to migrate to the new syntax.
+
+-l::
+--list::
+	Replaced by `git config list`.
+
 CONFIGURATION
 -------------
 `pager.config` is only respected when listing configuration, i.e.,
when -using `--list` or any of the `--get-*` which may return multiple results.
+using `list` or any of the `--get-*` which may return multiple results.
 The default is to use a pager.

 [[FILES]]
diff --git a/builtin/config.c b/builtin/config.c index
59877065f8..f89ddce8da 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -16,10 +16,16 @@
 #include "worktree.h"

 static const char *const builtin_config_usage[] = {
+	N_("git config list [<file-option>] [<display-option>]
+[--includes]"),
 	N_("git config [<options>]"),
 	NULL
 };

+static const char *const builtin_config_list_usage[] = {
+	N_("git config list [<file-option>] [<display-option>] [--includes]"),
+	NULL
+};
+
 static char *key;
 static regex_t *key_regexp;
 static const char *value_pattern;
@@ -33,6 +39,7 @@ static char delim = '=';  static char key_delim = '
';  static char term = '\n';

+static parse_opt_subcommand_fn *subcommand;
 static int use_global_config, use_system_config, use_local_config;
static int use_worktree_config;  static struct git_config_source
given_config_source; @@ -706,14 +713,24 @@ static void
handle_nul(void) {
 	}
 }

+#define CONFIG_LOCATION_OPTIONS \
+	OPT_GROUP(N_("Config file location")), \
+	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")), \
+	OPT_BOOL(0, "system", &use_system_config, N_("use system config
file")), \
quoted
+	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")), \
+	OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree
config file")), \
quoted
+	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given
config file")), \
quoted
+	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"),
+N_("read config from given blob object"))
+
+#define CONFIG_DISPLAY_OPTIONS \
+	OPT_GROUP(N_("Display options")), \
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")), \
+	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names
only")), \
quoted
+	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file,
standard input, blob, command line)")), \
quoted
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config
+(worktree, local, global, system, command)"))
+
 static struct option builtin_config_options[] = {
-	OPT_GROUP(N_("Config file location")),
-	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
-	OPT_BOOL(0, "system", &use_system_config, N_("use system config
file")),
quoted
-	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
-	OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree
config file")),
quoted
-	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given
config file")),
quoted
-	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"),
N_("read config from given blob object")),
quoted
+	CONFIG_LOCATION_OPTIONS,
 	OPT_GROUP(N_("Action")),
 	OPT_CMDMODE(0, "get", &actions, N_("get value: name [<value-
pattern>]"), ACTION_GET),
quoted
 	OPT_CMDMODE(0, "get-all", &actions, N_("get all values: key
[<value-pattern>]"), ACTION_GET_ALL), @@ -737,15 +754,12 @@ static struct
option builtin_config_options[] = {
quoted
 	OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or
string"), TYPE_BOOL_OR_STR),
quoted
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or
directory name)"), TYPE_PATH),
quoted
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry
date"), TYPE_EXPIRY_DATE),
+	CONFIG_DISPLAY_OPTIONS,
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
-	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names
only")),
quoted
-	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include
directives on lookup")),
quoted
-	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file,
standard input, blob, command line)")),
quoted
-	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config
(worktree, local, global, system, command)")),
quoted
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use
default value when missing entry")),
quoted
 	OPT_STRING(0, "comment", &comment_arg, N_("value"), N_("human-
readable comment string (# will be prepended as needed)")),
quoted
 	OPT_BOOL(0, "fixed-value", &fixed_value, N_("use string equality
when comparing values to 'value-pattern'")),
+	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include
+directives on lookup")),
 	OPT_END(),
 };
@@ -754,6 +768,42 @@ static NORETURN void usage_builtin_config(void)
 	usage_with_options(builtin_config_usage, builtin_config_options);  }

+static int cmd_config_list(int argc, const char **argv, const char
+*prefix) {
+	struct option opts[] = {
+		CONFIG_LOCATION_OPTIONS,
+		CONFIG_DISPLAY_OPTIONS,
+		OPT_GROUP(N_("Other")),
+		OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect
include directives on lookup")),
quoted
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, prefix, opts, builtin_config_list_usage, 0);
+	check_argc(argc, 0, 0);
+
+	handle_config_location(prefix);
+	handle_nul();
+
+	setup_auto_pager("config", 1);
+
+	if (config_with_options(show_all_config, NULL,
+				&given_config_source, the_repository,
+				&config_options) < 0) {
+		if (given_config_source.file)
+			die_errno(_("unable to read config file '%s'"),
+				  given_config_source.file);
+		else
+			die(_("error processing config file(s)"));
+	}
+
+	return 0;
+}
+
+static struct option builtin_subcommand_options[] = {
+	OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
+	OPT_END(),
+};
+
 int cmd_config(int argc, const char **argv, const char *prefix)  {
 	char *value = NULL, *comment = NULL; @@ -763,6 +813,22 @@ int
cmd_config(int argc, const char **argv, const char *prefix)

 	given_config_source.file =
xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));

+	/*
+	 * This is somewhat hacky: we first parse the command line while
+	 * keeping all args intact in order to determine whether a subcommand
+	 * has been specified. If so, we re-parse it a second time, but this
+	 * time we drop KEEP_ARGV0. This is so that we don't munge the command
+	 * line in case no subcommand was given, which would otherwise confuse
+	 * us when parsing the legacy-style modes that don't use subcommands.
+	 */
+	argc = parse_options(argc, argv, prefix, builtin_subcommand_options,
builtin_config_usage,
quoted
+
PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_NO_INTERNAL_HELP|PARSE
_OPT_KEEP_ARGV0|PARSE_OPT_KEEP_UNKNOWN_OPT);
quoted
+	if (subcommand) {
+		argc = parse_options(argc, argv, prefix,
builtin_subcommand_options, builtin_config_usage,
quoted
+
PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_NO_INTERNAL_HELP|PARSE
_OPT_KEEP_UNKNOWN_OPT);
quoted
+		return subcommand(argc, argv, prefix);
+	}
+
 	argc = parse_options(argc, argv, prefix, builtin_config_options,
 			     builtin_config_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION); diff --git
a/t/t1300-config.sh
quoted
b/t/t1300-config.sh index 86dc70769a..f77d2f7847 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -11,6 +11,20 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh

+for mode in legacy subcommands
+do
+
+case "$mode" in
+legacy)
+	mode_prefix="--"
+	;;
+subcommands)
+	mode_prefix=""
+	;;
+*)
+	BUG "unknown mode $mode";;
+esac
+
 test_expect_success 'setup whitespace config' '
 	sed -e "s/^|//" \
 	    -e "s/[$]$//" \
@@ -460,11 +474,11 @@ version.1.2.3eX.alpha=beta  EOF

 test_expect_success 'working --list' '
-	git config --list > output &&
+	git config ${mode_prefix}list > output &&
 	test_cmp expect output
 '
 test_expect_success '--list without repo produces empty output' '
-	git --git-dir=nonexistent config --list >output &&
+	git --git-dir=nonexistent config ${mode_prefix}list >output &&
 	test_must_be_empty output
 '
@@ -476,7 +490,7 @@ version.1.2.3eX.alpha  EOF

 test_expect_success '--name-only --list' '
-	git config --name-only --list >output &&
+	git config ${mode_prefix}list --name-only >output &&
 	test_cmp expect output
 '
@@ -614,17 +628,17 @@ ein.bahn=strasse  EOF

 test_expect_success 'alternative GIT_CONFIG' '
-	GIT_CONFIG=other-config git config --list >output &&
+	GIT_CONFIG=other-config git config ${mode_prefix}list >output &&
 	test_cmp expect output
 '

 test_expect_success 'alternative GIT_CONFIG (--file)' '
-	git config --file other-config --list >output &&
+	git config ${mode_prefix}list --file other-config >output &&
 	test_cmp expect output
 '

 test_expect_success 'alternative GIT_CONFIG (--file=-)' '
-	git config --file - --list <other-config >output &&
+	git config ${mode_prefix}list --file - <other-config >output &&
 	test_cmp expect output
 '
@@ -637,6 +651,7 @@ test_expect_success 'editing stdin is an error' '
 '

 test_expect_success 'refer config from subdirectory' '
+	test_when_finished "rm -r x" &&
 	mkdir x &&
 	test_cmp_config -C x strasse --file=../other-config --get ein.bahn
'
@@ -847,7 +862,7 @@ test_expect_success 'line number is reported correctly' '
 '

 test_expect_success 'invalid stdin config' '
-	echo "[broken" | test_must_fail git config --list --file - >output 2>&1 &&
+	echo "[broken" | test_must_fail git config ${mode_prefix}list --file
+- >output 2>&1 &&
 	test_grep "bad config line 1 in standard input" output  '
@@ -1139,7 +1154,7 @@ section.quotecont=cont;inued  EOF

 test_expect_success 'value continued on next line' '
-	git config --list > result &&
+	git config ${mode_prefix}list > result &&
 	test_cmp expect result
 '
@@ -1163,7 +1178,7 @@ Qsection.sub=section.val4
Qsection.sub=section.val5Q  EOF  test_expect_success '--null --list' '
-	git config --null --list >result.raw &&
+	git config ${mode_prefix}list --null >result.raw &&
 	nul_to_q <result.raw >result &&
 	echo >>result &&
 	test_cmp expect result
@@ -1198,6 +1213,7 @@ test_expect_success 'inner whitespace kept verbatim,
horizontal tabs and spaces'
quoted
 '

 test_expect_success SYMLINKS 'symlinked configuration' '
+	test_when_finished "rm myconfig" &&
 	ln -s notyet myconfig &&
 	git config --file=myconfig test.frotz nitfol &&
 	test -h myconfig &&
@@ -1218,10 +1234,11 @@ test_expect_success SYMLINKS 'symlinked
configuration' '
quoted
 '

 test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
+	test_when_finished "rm linktonada linktolinktonada" &&
 	ln -s doesnotexist linktonada &&
 	ln -s linktonada linktolinktonada &&
-	test_must_fail git config --file=linktonada --list &&
-	test_must_fail git config --file=linktolinktonada --list
+	test_must_fail git config ${mode_prefix}list --file=linktonada &&
+	test_must_fail git config ${mode_prefix}list --file=linktolinktonada
 '

 test_expect_success 'check split_cmdline return' '
@@ -1478,7 +1495,7 @@ do
 done

 test_expect_success 'git -c is not confused by empty environment' '
-	GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list
+	GIT_CONFIG_PARAMETERS="" git -c x.one=1 config ${mode_prefix}list
 '

 test_expect_success 'GIT_CONFIG_PARAMETERS handles old-style entries' '
@@ -1669,31 +1686,31 @@ test_expect_success 'git config ignores pairs with
empty count' '
quoted
 '

 test_expect_success 'git config fails with invalid count' '
-	test_must_fail env GIT_CONFIG_COUNT=10a git config --list 2>error &&
+	test_must_fail env GIT_CONFIG_COUNT=10a git config
+${mode_prefix}list 2>error &&
 	test_grep "bogus count" error &&
-	test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config --
list 2>error &&
quoted
+	test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config
+${mode_prefix}list 2>error &&
 	test_grep "too many entries" error
 '

 test_expect_success 'git config fails with missing config key' '
 	test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value"
\
quoted
-		git config --list 2>error &&
+		git config ${mode_prefix}list 2>error &&
 	test_grep "missing config key" error  '

 test_expect_success 'git config fails with missing config value' '
 	test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \
-		git config --list 2>error &&
+		git config ${mode_prefix}list 2>error &&
 	test_grep "missing config value" error  '

 test_expect_success 'git config fails with invalid config pair key' '
 	test_must_fail env GIT_CONFIG_COUNT=1 \
 		GIT_CONFIG_KEY_0= GIT_CONFIG_VALUE_0=value \
-		git config --list &&
+		git config ${mode_prefix}list &&
 	test_must_fail env GIT_CONFIG_COUNT=1 \
 		GIT_CONFIG_KEY_0=missing-section GIT_CONFIG_VALUE_0=value
\
quoted
-		git config --list
+		git config ${mode_prefix}list
 '

 test_expect_success 'environment overrides config file' '
@@ -1733,7 +1750,7 @@ test_expect_success 'git config --edit works' '
 	git config -f tmp test.value no &&
 	echo test.value=yes >expect &&
 	GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit &&
-	git config -f tmp --list >actual &&
+	git config ${mode_prefix}list -f tmp >actual &&
 	test_cmp expect actual
 '
@@ -1742,7 +1759,7 @@ test_expect_success 'git config --edit respects
core.editor' '
quoted
 	echo test.value=yes >expect &&
 	test_config core.editor "echo [test]value=yes >" &&
 	git config -f tmp --edit &&
-	git config -f tmp --list >actual &&
+	git config ${mode_prefix}list -f tmp >actual &&
 	test_cmp expect actual
 '
@@ -2093,7 +2110,7 @@ test_expect_success '--show-origin with --list' '
 	command line:	user.cmdline=true
 	EOF
 	GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=user.environ
GIT_CONFIG_VALUE_0=true\
quoted
-		git -c user.cmdline=true config --list --show-origin >output &&
+		git -c user.cmdline=true config ${mode_prefix}list --show-origin
+>output &&
 	test_cmp expect output
 '
@@ -2110,7 +2127,7 @@ test_expect_success '--show-origin with --list --null' '
 	includeQcommand line:Quser.cmdline
 	trueQ
 	EOF
-	git -c user.cmdline=true config --null --list --show-origin >output.raw &&
+	git -c user.cmdline=true config ${mode_prefix}list --null
+--show-origin >output.raw &&
 	nul_to_q <output.raw >output &&
 	# The here-doc above adds a newline that the --null output would not
 	# include. Add it here to make the two comparable.
@@ -2124,7 +2141,7 @@ test_expect_success '--show-origin with single file' '
 	file:.git/config	user.override=local
 	file:.git/config	include.path=../include/relative.include
 	EOF
-	git config --local --list --show-origin >output &&
+	git config ${mode_prefix}list --local --show-origin >output &&
 	test_cmp expect output
 '
@@ -2162,7 +2179,7 @@ test_expect_success !MINGW '--show-origin escape
special file name characters' '
quoted
 	cat >expect <<-\EOF &&
 	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
-	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
+	git config ${mode_prefix}list --file "$WEIRDLY_NAMED_FILE"
+--show-origin >output &&
 	test_cmp expect output
 '
@@ -2170,7 +2187,7 @@ test_expect_success '--show-origin stdin' '
 	cat >expect <<-\EOF &&
 	standard input:	user.custom=true
 	EOF
-	git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output
&&
quoted
+	git config ${mode_prefix}list --file - --show-origin
+<"$CUSTOM_CONFIG_FILE" >output &&
 	test_cmp expect output
 '
@@ -2197,7 +2214,7 @@ test_expect_success '--show-origin blob' '
 		cat >expect <<-EOF &&
 		blob:$blob	user.custom=true
 		EOF
-		git config --blob=$blob --show-origin --list >output &&
+		git config ${mode_prefix}list --blob=$blob --show-origin >output
&&
quoted
 		test_cmp expect output
 	)
 '
@@ -2213,7 +2230,7 @@ test_expect_success '--show-origin blob ref' '
 		cp "$CUSTOM_CONFIG_FILE" custom.conf &&
 		git add custom.conf &&
 		git commit -m "new config file" &&
-		git config --blob=main:custom.conf --show-origin --list >output &&
+		git config ${mode_prefix}list --blob=main:custom.conf --show-
origin
quoted
+>output &&
 		test_cmp expect output
 	)
 '
@@ -2239,13 +2256,14 @@ test_expect_success '--show-scope with --list' '
 	worktree	user.worktree=true
 	command	user.cmdline=true
 	EOF
+	test_when_finished "git worktree remove wt1" &&
 	git worktree add wt1 &&
 	# We need these to test for worktree scope, but outside of this
 	# test, this is just noise
 	test_config core.repositoryformatversion 1 &&
 	test_config extensions.worktreeConfig true &&
 	git config --worktree user.worktree true &&
-	git -c user.cmdline=true config --list --show-scope >output &&
+	git -c user.cmdline=true config ${mode_prefix}list --show-scope
+>output &&
 	test_cmp expect output
 '
@@ -2254,7 +2272,7 @@ test_expect_success !MINGW '--show-scope with --
blob' '
quoted
 	cat >expect <<-EOF &&
 	command	user.custom=true
 	EOF
-	git config --blob=$blob --show-scope --list >output &&
+	git config ${mode_prefix}list --blob=$blob --show-scope >output &&
 	test_cmp expect output
 '
@@ -2264,7 +2282,7 @@ test_expect_success '--show-scope with --local' '
 	local	user.override=local
 	local	include.path=../include/relative.include
 	EOF
-	git config --local --list --show-scope >output &&
+	git config ${mode_prefix}list --local --show-scope >output &&
 	test_cmp expect output
 '
@@ -2288,7 +2306,7 @@ test_expect_success '--show-scope with --show-origin'
'
quoted
 	local	file:.git/../include/relative.include	user.relative=include
 	command	command line:	user.cmdline=true
 	EOF
-	git -c user.cmdline=true config --list --show-origin --show-scope >output
&&
quoted
+	git -c user.cmdline=true config ${mode_prefix}list --show-origin
+--show-scope >output &&
 	test_cmp expect output
 '
@@ -2329,7 +2347,7 @@ test_expect_success 'override global and system
config' '
quoted
 	global	home.config=true
 	local	local.config=true
 	EOF
-	git config --show-scope --list >output &&
+	git config ${mode_prefix}list --show-scope >output &&
 	test_cmp expect output &&

 	cat >expect <<-EOF &&
@@ -2338,20 +2356,20 @@ test_expect_success 'override global and system
config' '
quoted
 	local	local.config=true
 	EOF
 	GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=custom-system-
config GIT_CONFIG_GLOBAL=custom-global-config \
quoted
-		git config --show-scope --list >output &&
+		git config ${mode_prefix}list --show-scope >output &&
 	test_cmp expect output &&

 	cat >expect <<-EOF &&
 	local	local.config=true
 	EOF
 	GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=/dev/null
GIT_CONFIG_GLOBAL=/dev/null \
quoted
-		git config --show-scope --list >output &&
+		git config ${mode_prefix}list --show-scope >output &&
 	test_cmp expect output
 '

 test_expect_success 'override global and system config with missing file' '
-	test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist
GIT_CONFIG_SYSTEM=/dev/null git config --global --list &&
quoted
-	test_must_fail env GIT_CONFIG_GLOBAL=/dev/null
GIT_CONFIG_SYSTEM=does-not-exist git config --system --list &&
quoted
+	test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist
GIT_CONFIG_SYSTEM=/dev/null git config ${mode_prefix}list --global &&
quoted
+	test_must_fail env GIT_CONFIG_GLOBAL=/dev/null
+GIT_CONFIG_SYSTEM=does-not-exist git config ${mode_prefix}list
+--system &&
 	GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=does-not-exist
git version  '
@@ -2478,7 +2496,7 @@ test_expect_success 'set all config with value-pattern' '
 	# no match => add new entry
 	cp initial config &&
 	git config --file=config abc.key two a+ &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-\EOF &&
 	abc.key=one
 	abc.key=two
@@ -2491,7 +2509,7 @@ test_expect_success 'set all config with value-pattern' '

 	# multiple values, no match => add
 	git config --file=config abc.key three a+ &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-\EOF &&
 	abc.key=one
 	abc.key=two
@@ -2501,7 +2519,7 @@ test_expect_success 'set all config with value-pattern' '

 	# single match => replace
 	git config --file=config abc.key four h+ &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-\EOF &&
 	abc.key=one
 	abc.key=two
@@ -2516,7 +2534,7 @@ test_expect_success '--replace-all and value-pattern' '
 	git config --file=config --add abc.key two &&
 	git config --file=config --add abc.key three &&
 	git config --file=config --replace-all abc.key four "o+" &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-\EOF &&
 	abc.key=four
 	abc.key=three
@@ -2534,7 +2552,7 @@ test_expect_success 'refuse --fixed-value for
incompatible actions' '
quoted
 	test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null
bogus &&
quoted
 	test_must_fail git config --file=config --fixed-value --rename-section dev null
&&
quoted
 	test_must_fail git config --file=config --fixed-value --remove-section dev &&
-	test_must_fail git config --file=config --fixed-value --list &&
+	test_must_fail git config ${mode_prefix}list --file=config
+--fixed-value &&
 	test_must_fail git config --file=config --fixed-value --get-color dev.null &&
 	test_must_fail git config --file=config --fixed-value
--get-colorbool dev.null &&
@@ -2555,7 +2573,7 @@ test_expect_success '--fixed-value uses exact string
matching' '
quoted
 	cp initial config &&
 	git config --file=config fixed.test bogus "$META" &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-EOF &&
 	fixed.test=$META
 	fixed.test=bogus
@@ -2564,7 +2582,7 @@ test_expect_success '--fixed-value uses exact string
matching' '
quoted
 	cp initial config &&
 	git config --file=config --fixed-value fixed.test bogus "$META" &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-\EOF &&
 	fixed.test=bogus
 	EOF
@@ -2582,7 +2600,7 @@ test_expect_success '--fixed-value uses exact string
matching' '
quoted
 	cp initial config &&
 	git config --file=config --replace-all fixed.test bogus "$META" &&
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-EOF &&
 	fixed.test=$META
 	fixed.test=bogus
@@ -2590,7 +2608,7 @@ test_expect_success '--fixed-value uses exact string
matching' '
quoted
 	test_cmp expect actual &&

 	git config --file=config --fixed-value --replace-all fixed.test bogus "$META"
&&
quoted
-	git config --file=config --list >actual &&
+	git config ${mode_prefix}list --file=config >actual &&
 	cat >expect <<-EOF &&
 	fixed.test=bogus
 	fixed.test=bogus
@@ -2751,4 +2769,6 @@ test_expect_success 'specifying multiple modes causes
failure' '
quoted
 	test_cmp expect err
 '

+done
+
Nit: Wouldn't it be better if the tests are indented here? That way you know it's part
of a loop.
Removing the --list option is going to break backward compatibility for users who script the use of config for things like setup, clone automation, etc. Adding list as a sub-command could (but should not) cause ambiguities between a list and configuration value. If you are going to add 'list', please do not remove '--list'. That is a breaking change.

Thanks,
Randall
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help