git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / Atom feed
* [PATCH 0/1] config: allow user to know scope of config options
@ 2019-12-18  1:11 Matthew Rogers via GitGitGadget
  2019-12-18  1:11 ` [PATCH 1/1] " Matthew Rogers via GitGitGadget
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
  0 siblings, 2 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2019-12-18  1:11 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Junio C Hamano

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

Matthew Rogers (1):
  config: allow user to know scope of config options

 builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------
 t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 8 deletions(-)


base-commit: b02fd2accad4d48078671adf38fe5b5976d77304
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/478
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 1/1] config: allow user to know scope of config options
  2019-12-18  1:11 [PATCH 0/1] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
@ 2019-12-18  1:11 ` " Matthew Rogers via GitGitGadget
  2019-12-18 19:46   ` Junio C Hamano
  2019-12-18 22:45   ` Philip Oakley
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
  1 sibling, 2 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2019-12-18  1:11 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Junio C Hamano, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Add new option --show-scope which allows a user to know what the scope
of listed config options are (local/global/system/etc.).

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------
 t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..9a9c2d12f2 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,10 +29,11 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -151,10 +152,11 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (system, global, local, command line)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -178,23 +180,63 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
 	strbuf_addch(buf, term);
 }
 
+static const char *scope_to_string(enum config_scope scope) {
+	/*
+	 * --local, --global, and --system work the same as --file so there's
+	 * no easy way for the parser to tell the difference when it is
+	 * setting the scope, so we use our information about which options
+	 * were passed
+	 */
+	if (use_local_config || scope == CONFIG_SCOPE_REPO) {
+		return "local";
+	} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {
+		return "global";
+	} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {
+		return "system";
+	} else if (given_config_source.use_stdin ||
+		given_config_source.blob ||
+		given_config_source.file ||
+		scope == CONFIG_SCOPE_CMDLINE) {
+		return "command line";
+	} else {
+		return "unknown";
+	}
+}
+
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addch(buf, '(');
+	if (end_nul)
+		strbuf_addstr(buf, N_(scope));
+	else
+		quote_c_style(scope, buf, NULL, 0);
+	strbuf_addch(buf, ')');
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
-		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
+		/* Use fwrite as "buf" can contain \0's if "end_nul" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
 	}
@@ -213,6 +255,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -678,7 +722,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..098f305bdd 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1766,6 +1766,57 @@ test_expect_success !MINGW '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		(global)	user.global=true
+		(global)	user.override=global
+		(global)	include.path=$INCLUDE_DIR/absolute.include
+		(global)	user.absolute=include
+		(local)	user.local=true
+		(local)	user.override=local
+		(local)	include.path=../include/relative.include
+		(local)	user.relative=include
+		(command line)	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		(command line)	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		(local)	user.local=true
+		(local)	user.override=local
+		(local)	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		(global)	file:$HOME/.gitconfig	user.global=true
+		(global)	file:$HOME/.gitconfig	user.override=global
+		(global)	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		(global)	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		(local)	file:.git/config	user.local=true
+		(local)	file:.git/config	user.override=local
+		(local)	file:.git/config	include.path=../include/relative.include
+		(local)	file:.git/../include/relative.include	user.relative=include
+		(command line)	command line:	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-origin --show-scope >output &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-18  1:11 ` [PATCH 1/1] " Matthew Rogers via GitGitGadget
@ 2019-12-18 19:46   ` Junio C Hamano
  2019-12-19  5:05     ` Jeff King
  2019-12-18 22:45   ` Philip Oakley
  1 sibling, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2019-12-18 19:46 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> -static int end_null;
> +static int end_nul;
> -	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
> +	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
> -	const char term = end_null ? '\0' : '\t';
> +	const char term = end_nul ? '\0' : '\t';
> -	if (end_null)
> +	if (end_nul)

These are correct changes, but is unrelated noise in the context of
the theme of the patch, no?

> +static const char *scope_to_string(enum config_scope scope) {
> +	/*
> +	 * --local, --global, and --system work the same as --file so there's
> +	 * no easy way for the parser to tell the difference when it is
> +	 * setting the scope, so we use our information about which options
> +	 * were passed
> +	 */
> +	if (use_local_config || scope == CONFIG_SCOPE_REPO) {
> +		return "local";
> +	} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {
> +		return "global";
> +	} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {
> +		return "system";

The above is slightly tricky; --global/--system/--local are made
mutually exclusive in the higher level, so if any of them is set,
we do not even need to look at the "scope" to tell what kind of
source we are reading from.

> +	} else if (given_config_source.use_stdin ||
> +		given_config_source.blob ||
> +		given_config_source.file ||
> +		scope == CONFIG_SCOPE_CMDLINE) {
> +		return "command line";

I am not sure what the implication of saying "they came from the
command line" when we read from the standard input or from a blob.

> +	} else {
> +		return "unknown";
> +	}
> +}

In any case, the need for such logic that says "scope might not say
it is REPO, but when use_local_config is true, we are doing a local
config" implies that "scope" parameter the caller of this function
has is not set correctly when these options are used---would that be
the real bug that needs fixing, rather than getting "worked around"
with a code like this?

It almost makes me point fingers at config.c::config_with_options()
where config_source is inspected and git_config_from_*() helpers are
called without setting the current_parsing_scope.  Unlike these
cases, when do_git_config_sequence() is called from that function,
the scope is recorded in the variable before each standard config
source file is opened and read.  What would we be breaking if we
taught the function to set the current_parsing_scope variable
correctly even when reading from the config_source?  That would
certainly simplify this function quite a lot, but if the other parts
of the codebase relies on the current behaviour, we cannot make such
a change lightly.

> +static void show_config_scope(struct strbuf *buf)
> +{
> +	const char term = end_nul ? '\0' : '\t';
> +	const char *scope = scope_to_string(current_config_scope());
> +
> +	strbuf_addch(buf, '(');
> +	if (end_nul)
> +		strbuf_addstr(buf, N_(scope));
> +	else
> +		quote_c_style(scope, buf, NULL, 0);

Isn't this overkill?  I think this code was copied-and-pasted from
the other function that needs to show an arbitrary end-user supplied
data which is a pathname, so it makes perfect sense to use c-style
quoting, but the token scope_to_string() returns is taken from a
bounded set that doesn't require such quoting, no?

> +	strbuf_addch(buf, ')');
> +	strbuf_addch(buf, term);
> +}
> +

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-18  1:11 ` [PATCH 1/1] " Matthew Rogers via GitGitGadget
  2019-12-18 19:46   ` Junio C Hamano
@ 2019-12-18 22:45   ` Philip Oakley
  2019-12-19  0:12     ` mattr94
  1 sibling, 1 reply; 98+ messages in thread
From: Philip Oakley @ 2019-12-18 22:45 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget, git; +Cc: Matthew Rogers, Junio C Hamano

Hi Matthew,

On 18/12/2019 01:11, Matthew Rogers via GitGitGadget wrote:
> From: Matthew Rogers <mattr94@gmail.com>
>
> Add new option --show-scope which allows a user to know what the scope
> of listed config options are (local/global/system/etc.).
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------
>  t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 103 insertions(+), 8 deletions(-)

Doesn't this also need a man page update as well for adding the option
to the synopsis.

The commit message doesn't fully highlight that the config list will
often be all the users config values, so each value will be
disambiguated/identified as to it's origin.

Philip

^ permalink raw reply	[flat|nested] 98+ messages in thread

* RE: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-18 22:45   ` Philip Oakley
@ 2019-12-19  0:12     ` mattr94
  2019-12-19 17:56       ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: mattr94 @ 2019-12-19  0:12 UTC (permalink / raw)
  To: Philip Oakley, Matthew Rogers via GitGitGadget, git; +Cc: Junio C Hamano

Junio,

>These are correct changes, but is unrelated noise in the context of
>the theme of the patch, no?

I think that's the case, would the recommended course of action be to
move these changes into its own commit? 


>> +     if (use_local_config || scope == CONFIG_SCOPE_REPO) {
>> +             return "local";
>> +     } else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {
>> +             return "global";
>> +     } else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {
>> +             return "system";
>
>The above is slightly tricky; --global/--system/--local are made
>mutually exclusive in the higher level, so if any of them is set,
>we do not even need to look at the "scope" to tell what kind of
>source we are reading from.

So the way I structured these was to mirror the way other parts 
of this file check if we should be doing a --local, etc. and mirrored 
that here.  This could definitely be cleaned up if we change the behavior
with how --local, etc. set the current_config_scope.


>> +     } else if (given_config_source.use_stdin ||
>> +             given_config_source.blob ||
>> +             given_config_source.file ||
>> +             scope == CONFIG_SCOPE_CMDLINE) {
>> +             return "command line";
>
>I am not sure what the implication of saying "they came from the
>command line" when we read from the standard input or from a blob.

I agree with you here, I only put this as "command line" 
because they came from a place that was ultimately fed in from 
command line options (--file/--blob).  I wouldn't have a problem with 
calling them out as their own scope ("file", "blob", "stdin").


>> +     } else {
>> +             return "unknown";
>> +     }
>> +}
>
>In any case, the need for such logic that says "scope might not say
>it is REPO, but when use_local_config is true, we are doing a local
>config" implies that "scope" parameter the caller of this function
>has is not set correctly when these options are used---would that be
>the real bug that needs fixing, rather than getting "worked around"
>with a code like this?
>
>It almost makes me point fingers at config.c::config_with_options()
>where config_source is inspected and git_config_from_*() helpers are
>called without setting the current_parsing_scope.  Unlike these
>cases, when do_git_config_sequence() is called from that function,
>the scope is recorded in the variable before each standard config
>source file is opened and read.  What would we be breaking if we
>taught the function to set the current_parsing_scope variable
>correctly even when reading from the config_source?  That would
>certainly simplify this function quite a lot, but if the other parts
>of the codebase relies on the current behaviour, we cannot make such
>a change lightly.

From what I can tell from a cursory glance. the only two clients of 
this function are remote.c and upload-pack.c.  The usecase for remote.c
 mostly seems to be to determine the result of `remote_is_configured()`
which (more importantly) seems to be done when that iterates through 
the relevant configuration options.  Similarly for upload-pack.c.

I don't think it would be harmful for git config --local, etc. to set that
as we would normally intuit.


>> +static void show_config_scope(struct strbuf *buf)
>> +{
>> +     const char term = end_nul ? '\0' : '\t';
>> +     const char *scope = scope_to_string(current_config_scope());
>> +
>> +     strbuf_addch(buf, '(');
>> +     if (end_nul)
>> +             strbuf_addstr(buf, N_(scope));
>> +     else
>> +             quote_c_style(scope, buf, NULL, 0);
>
>Isn't this overkill?  I think this code was copied-and-pasted from
>the other function that needs to show an arbitrary end-user supplied
>data which is a pathname, so it makes perfect sense to use c-style
>quoting, but the token scope_to_string() returns is taken from a
>bounded set that doesn't require such quoting, no?

Yeah, I guess that is a copy+paste mistake.  I don't think its 
necessary since we control the input into this function, So I'll fix 
that.


Philip,

>Doesn't this also need a man page update as well for adding the option
>to the synopsis.
>
>The commit message doesn't fully highlight that the config list will
>often be all the users config values, so each value will be
>disambiguated/identified as to it's origin.

I'm agreed on these. So I'll look to readjust that.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-18 19:46   ` Junio C Hamano
@ 2019-12-19  5:05     ` Jeff King
  2019-12-19 17:51       ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Jeff King @ 2019-12-19  5:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git, Matthew Rogers

On Wed, Dec 18, 2019 at 11:46:06AM -0800, Junio C Hamano wrote:

> It almost makes me point fingers at config.c::config_with_options()
> where config_source is inspected and git_config_from_*() helpers are
> called without setting the current_parsing_scope.  Unlike these
> cases, when do_git_config_sequence() is called from that function,
> the scope is recorded in the variable before each standard config
> source file is opened and read.  What would we be breaking if we
> taught the function to set the current_parsing_scope variable
> correctly even when reading from the config_source?  That would
> certainly simplify this function quite a lot, but if the other parts
> of the codebase relies on the current behaviour, we cannot make such
> a change lightly.

As the author of the SCOPE enum, I think this is the right direction.
The only users of current_config_scope() are in config callbacks (e.g.,
upload_pack_config() checks it for the "packobjectshook"), which you
couldn't trigger via "git config" anyway.

The main reason I didn't set the scope before in config_with_options()
is that it's not given the scope at all; git-config resolves it to the
filename. So if git_config_source grows an enum to select the type, and
all that filename-resolution gets pushed down into config_with_options(),
the whole thing would fall out naturally, I think.

-Peff

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-19  5:05     ` Jeff King
@ 2019-12-19 17:51       ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2019-12-19 17:51 UTC (permalink / raw)
  To: Jeff King; +Cc: Matthew Rogers via GitGitGadget, git, Matthew Rogers

Jeff King <peff@peff.net> writes:

> ... So if git_config_source grows an enum to select the type, and
> all that filename-resolution gets pushed down into config_with_options(),
> the whole thing would fall out naturally, I think.

Makes sense.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-19  0:12     ` mattr94
@ 2019-12-19 17:56       ` Junio C Hamano
  2019-12-20 22:58         ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2019-12-19 17:56 UTC (permalink / raw)
  To: mattr94; +Cc: Philip Oakley, Matthew Rogers via GitGitGadget, git

<mattr94@gmail.com> writes:

>>These are correct changes, but is unrelated noise in the context of
>>the theme of the patch, no?
>
> I think that's the case, would the recommended course of action be to
> move these changes into its own commit? 
>

Yup, and it generally is a good idea to make such a clean-up patch
either early in the series, or as a standalone patch (with a note
under three-dash lines that another topic is coming on top of the
cleanup), because it would be much less likely to introduce new bugs
and can be merged quicly to 'next' and then to 'master' to serve as
a base to build your other changes on top.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-19 17:56       ` Junio C Hamano
@ 2019-12-20 22:58         ` Matt Rogers
  2019-12-21  2:37           ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Matt Rogers @ 2019-12-20 22:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Philip Oakley, Matthew Rogers via GitGitGadget, git

Philip,

>The commit message doesn't fully highlight that the config list will
>often be all the users config values, so each value will be
>disambiguated/identified as to it's origin.

I don't really understand what you mean by "it's origin" here.  When
you say origin, do you mean in the "--show-origin" sense of "file/blob/etc."
or something else? Because scope is kind of an orthogonal concept to origin
in that sense as you can have files with different origins but the same scope.

Thanks,
Matt


On Thu, Dec 19, 2019 at 12:56 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> <mattr94@gmail.com> writes:
>
> >>These are correct changes, but is unrelated noise in the context of
> >>the theme of the patch, no?
> >
> > I think that's the case, would the recommended course of action be to
> > move these changes into its own commit?
> >
>
> Yup, and it generally is a good idea to make such a clean-up patch
> either early in the series, or as a standalone patch (with a note
> under three-dash lines that another topic is coming on top of the
> cleanup), because it would be much less likely to introduce new bugs
> and can be merged quicly to 'next' and then to 'master' to serve as
> a base to build your other changes on top.
>


-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-20 22:58         ` Matt Rogers
@ 2019-12-21  2:37           ` Junio C Hamano
  2019-12-21  3:08             ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2019-12-21  2:37 UTC (permalink / raw)
  To: Matt Rogers; +Cc: Philip Oakley, Matthew Rogers via GitGitGadget, git

Matt Rogers <mattr94@gmail.com> writes:

> Philip,
>
>>The commit message doesn't fully highlight that the config list will
>>often be all the users config values, so each value will be
>>disambiguated/identified as to it's origin.
>
> I don't really understand what you mean by "it's origin" here.  When
> you say origin, do you mean in the "--show-origin" sense of "file/blob/etc."
> or something else? Because scope is kind of an orthogonal concept to origin
> in that sense as you can have files with different origins but the same scope.

I do not think origin and scope are orghogonal, though.  Can the
same file appear as the source for different configuration var-value
pair in two different scopes?

It is likely that you can _guess_ with high precision that given a
pathname reported by --show-origin what scope it is in.  It on the
other hand is not so trivial given a scope to guess which exact file
a var-value pair came from, I would think.\

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-21  2:37           ` Junio C Hamano
@ 2019-12-21  3:08             ` Matt Rogers
  2019-12-21 23:47               ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Matt Rogers @ 2019-12-21  3:08 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Philip Oakley, Matthew Rogers via GitGitGadget, git

On Fri, Dec 20, 2019 at 9:37 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> I do not think origin and scope are orghogonal, though.  Can the
> same file appear as the source for different configuration var-value
> pair in two different scopes?

I meant orthogonal in two senses:

That given the current implementation you don't need to have both
options active at
the same time but can have them active at both times.

And that origin and scope correlate, but aren't necessarily
one-for-one.  For example, --show-origin lists in a known order, but it follows
includes and lists the origin as the included file.  so if you include a file
globally which has includeif "gitdir:..." directives then it can get hairy when
all your config files are structured like that.

Although, to be fair I doubt that that kind of situation is normal

>
> It is likely that you can _guess_ with high precision that given a
> pathname reported by --show-origin what scope it is in.  It on the
> other hand is not so trivial given a scope to guess which exact file
> a var-value pair came from, I would think.\

Normally yes, but things can get complicating depending on your
configuration/include situation.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/1] config: allow user to know scope of config options
  2019-12-21  3:08             ` Matt Rogers
@ 2019-12-21 23:47               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2019-12-21 23:47 UTC (permalink / raw)
  To: Matt Rogers; +Cc: Philip Oakley, Matthew Rogers via GitGitGadget, git

Matt Rogers <mattr94@gmail.com> writes:

> And that origin and scope correlate, but aren't necessarily
> one-for-one.

Yes, exactly.  When I see "orthogonal", I expect the word describes
things that do not correlate.

I can see values in the option that gives scope but not path in
order to write scripts that limits var-value pairs to be used
(e.g. "I do not want to be affected by the per-repository values",
"I do not trust settings that comes system-wide").  I also can see
values in the option that gives only path when debugging the
configuration file.

I briefly wondered, for the purpose of such "I do want to see only
those settings coming from these scopes" script, it may make more
sense to have the command _filter_ the var-value pairs, instead of
showing all of them with label, but that feature always exists ;-)

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v2 0/4] config: allow user to know scope of config options
  2019-12-18  1:11 [PATCH 0/1] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2019-12-18  1:11 ` [PATCH 1/1] " Matthew Rogers via GitGitGadget
@ 2020-01-09 10:16 ` " Matthew Rogers via GitGitGadget
  2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
                     ` (4 more replies)
  1 sibling, 5 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v1:

 * Cleaned up meaning of scoping, specifically separating "repo" into
   "local" and "worktree" as well as expanding "cmdline" into "command"
   scoping, added submodule scoping
 * Taught struct git_config_source to remember the scope of the command that
   is filling it out
 * do_git_config_sequence() now remembers the previous scope so that if it
   is called recursively it can remember where it was.
 * Added documentation for this new option

Matthew Rogers (4):
  config: fix typo in variable name
  config: fix config scope enum
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt | 15 +++++---
 builtin/config.c             | 66 ++++++++++++++++++++++++++++++------
 config.c                     | 15 ++++----
 config.h                     | 19 ++++++-----
 remote.c                     |  3 +-
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       |  8 +++--
 t/t1300-config.sh            | 50 +++++++++++++++++++++++++++
 upload-pack.c                |  3 +-
 9 files changed, 148 insertions(+), 35 deletions(-)


base-commit: 7a6a90c6ec48fc78c83d7090d6c1b95d8f3739c0
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v1:

 -:  ---------- > 1:  b40480f03a config: fix typo in variable name
 -:  ---------- > 2:  e8e05f3940 config: fix config scope enum
 -:  ---------- > 3:  8225273546 config: clarify meaning of command line scoping
 1:  ec699bb3e6 ! 4:  92ce9b7824 config: allow user to know scope of config options
     @@ -1,21 +1,62 @@
      Author: Matthew Rogers <mattr94@gmail.com>
      
     -    config: allow user to know scope of config options
     +    config: add '--show-scope' to print the scope of a config value
      
     -    Add new option --show-scope which allows a user to know what the scope
     -    of listed config options are (local/global/system/etc.).
     +    When a user queries config values with --show-origin, often it's
     +    difficult to determine what the actual "scope" (local, global, etc.) of
     +    a given value is based on just the origin file.
     +
     +    Teach 'git config' the '--show-scope' option to print the scope of all
     +    displayed config values.  Note that we should never see anything of
     +    "submodule" scope as that is only ever used by submodule-config.c when
     +    parsing the '.gitmodules' file.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
      
     + diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
     + --- a/Documentation/git-config.txt
     + +++ b/Documentation/git-config.txt
     +@@
     + SYNOPSIS
     + --------
     + [verse]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
     + 'git config' [<file-option>] [--type=<type>] --add name value
     + 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
     + 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
     + 'git config' [<file-option>] --unset name [value_regex]
     + 'git config' [<file-option>] --unset-all name [value_regex]
     + 'git config' [<file-option>] --rename-section old_name new_name
     + 'git config' [<file-option>] --remove-section name
     +-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
     ++'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
     +@@
     + 	the actual origin (config file path, ref, or blob id if
     + 	applicable).
     + 
     ++--show-scope::
     ++	Similar to `--show-origin` in that it augments the output of
     ++	all queried config options with the scope of that value 
     ++	(local, global, system, command).
     ++
     + --get-colorbool name [stdout-is-tty]::
     + 
     + 	Find the color setting for `name` (e.g. `color.diff`) and output
     +
       diff --git a/builtin/config.c b/builtin/config.c
       --- a/builtin/config.c
       +++ b/builtin/config.c
      @@
     - static struct git_config_source given_config_source;
     - static int actions, type;
     - static char *default_value;
     --static int end_null;
     -+static int end_nul;
       static int respect_includes_opt = -1;
       static struct config_options config_options;
       static int show_origin;
     @@ -24,69 +65,41 @@
       #define ACTION_GET (1<<0)
       #define ACTION_GET_ALL (1<<1)
      @@
     - 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
     - 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
     - 	OPT_GROUP(N_("Other")),
     --	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
     -+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
       	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
       	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
       	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
     -+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (system, global, local, command line)")),
     ++	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
       	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
       	OPT_END(),
       };
      @@
     - 
     - static void show_config_origin(struct strbuf *buf)
     - {
     --	const char term = end_null ? '\0' : '\t';
     -+	const char term = end_nul ? '\0' : '\t';
     - 
     - 	strbuf_addstr(buf, current_config_origin_type());
     - 	strbuf_addch(buf, ':');
     --	if (end_null)
     -+	if (end_nul)
     - 		strbuf_addstr(buf, current_config_name());
     - 	else
     - 		quote_c_style(current_config_name(), buf, NULL, 0);
       	strbuf_addch(buf, term);
       }
       
      +static const char *scope_to_string(enum config_scope scope) {
     -+	/*
     -+	 * --local, --global, and --system work the same as --file so there's
     -+	 * no easy way for the parser to tell the difference when it is
     -+	 * setting the scope, so we use our information about which options
     -+	 * were passed
     -+	 */
     -+	if (use_local_config || scope == CONFIG_SCOPE_REPO) {
     ++	switch (scope) {
     ++	case CONFIG_SCOPE_LOCAL:
      +		return "local";
     -+	} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {
     ++	case CONFIG_SCOPE_GLOBAL:
      +		return "global";
     -+	} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {
     ++	case CONFIG_SCOPE_SYSTEM:
      +		return "system";
     -+	} else if (given_config_source.use_stdin ||
     -+		given_config_source.blob ||
     -+		given_config_source.file ||
     -+		scope == CONFIG_SCOPE_CMDLINE) {
     -+		return "command line";
     -+	} else {
     ++	case CONFIG_SCOPE_WORKTREE:
     ++		return "worktree";
     ++	case CONFIG_SCOPE_COMMAND:
     ++		return "command";
     ++	case CONFIG_SCOPE_SUBMODULE:
     ++		return "submodule";
     ++	default:
      +		return "unknown";
      +	}
      +}
      +
     -+static void show_config_scope(struct strbuf *buf)
     -+{
     ++static void show_config_scope(struct strbuf *buf) {
      +	const char term = end_nul ? '\0' : '\t';
      +	const char *scope = scope_to_string(current_config_scope());
      +
     -+	strbuf_addch(buf, '(');
     -+	if (end_nul)
     -+		strbuf_addstr(buf, N_(scope));
     -+	else
     -+		quote_c_style(scope, buf, NULL, 0);
     -+	strbuf_addch(buf, ')');
     ++	strbuf_addstr(buf, N_(scope));
      +	strbuf_addch(buf, term);
      +}
      +
     @@ -96,33 +109,188 @@
      +	if (show_origin || show_scope) {
       		struct strbuf buf = STRBUF_INIT;
      -		show_config_origin(&buf);
     --		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
      +		if (show_scope)
      +			show_config_scope(&buf);
      +		if (show_origin)
      +			show_config_origin(&buf);
     -+		/* Use fwrite as "buf" can contain \0's if "end_nul" is set. */
     + 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
       		fwrite(buf.buf, 1, buf.len, stdout);
       		strbuf_release(&buf);
     - 	}
      @@
       
       static int format_config(struct strbuf *buf, const char *key_, const char *value_)
       {
      +	if (show_scope)
     -+		show_config_scope(buf);
     ++		show_config_origin(buf);
       	if (show_origin)
       		show_config_origin(buf);
       	if (show_keys)
      @@
     - 		config_options.git_dir = get_git_dir();
     + 	int nongit = !startup_info->have_repository;
     + 	char *value;
     + 
     ++
     ++
     + 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
     + 
     + 	argc = parse_options(argc, argv, prefix, builtin_config_options,
     +@@
     + 			!strcmp(given_config_source.file, "-")) {
     + 		given_config_source.file = NULL;
     + 		given_config_source.use_stdin = 1;
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     + 	}
     + 
     + 	if (use_global_config) {
     +@@
     + 			 */
     + 			die(_("$HOME not set"));
     + 
     ++		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
     ++
     + 		if (access_or_warn(user_config, R_OK, 0) &&
     + 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
     + 			given_config_source.file = xdg_config;
     +@@
     + 			free(xdg_config);
     + 		}
     + 	}
     +-	else if (use_system_config)
     ++	else if (use_system_config) {
     + 		given_config_source.file = git_etc_gitconfig();
     +-	else if (use_local_config)
     ++		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
     ++	} else if (use_local_config) {
     + 		given_config_source.file = git_pathdup("config");
     +-	else if (use_worktree_config) {
     ++		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     ++	} else if (use_worktree_config) {
     + 		struct worktree **worktrees = get_worktrees(0);
     + 		if (repository_format_worktree_config)
     + 			given_config_source.file = git_pathdup("config.worktree");
     +@@
     + 			      "section in \"git help worktree\" for details"));
     + 		else
     + 			given_config_source.file = git_pathdup("config");
     ++		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     + 		free_worktrees(worktrees);
     + 	} else if (given_config_source.file) {
     + 		if (!is_absolute_path(given_config_source.file) && prefix)
     + 			given_config_source.file =
     + 				prefix_filename(prefix, given_config_source.file);
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     ++	} else if (given_config_source.blob) {
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     + 	}
     + 
     ++
     + 	if (respect_includes_opt == -1)
     + 		config_options.respect_includes = !given_config_source.file;
     + 	else
     +
     + diff --git a/config.c b/config.c
     + --- a/config.c
     + +++ b/config.c
     +@@
     + 	char *xdg_config = xdg_config_home("config");
     + 	char *user_config = expand_user_path("~/.gitconfig", 0);
     + 	char *repo_config;
     ++	enum config_scope prev_parsing_scope = current_parsing_scope;
     + 
     + 	if (opts->commondir)
     + 		repo_config = mkpathdup("%s/config", opts->commondir);
     +@@
     + 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
     + 		die(_("unable to parse command-line config"));
     + 
     +-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
     ++	current_parsing_scope = prev_parsing_scope;
     + 	free(xdg_config);
     + 	free(user_config);
     + 	free(repo_config);
     +@@
     + 		data = &inc;
       	}
       
     --	if (end_null) {
     -+	if (end_nul) {
     - 		term = '\0';
     - 		delim = '\n';
     - 		key_delim = '\n';
     ++	if (config_source)
     ++		current_parsing_scope = config_source->scope;
     ++
     + 	/*
     + 	 * If we have a specific filename, use it. Otherwise, follow the
     + 	 * regular lookup sequence.
     +
     + diff --git a/config.h b/config.h
     + --- a/config.h
     + +++ b/config.h
     +@@
     + 
     + #define CONFIG_REGEX_NONE ((void *)1)
     + 
     ++enum config_scope {
     ++	CONFIG_SCOPE_UNKNOWN = 0,
     ++	CONFIG_SCOPE_SYSTEM,
     ++	CONFIG_SCOPE_GLOBAL,
     ++	CONFIG_SCOPE_LOCAL,
     ++	CONFIG_SCOPE_WORKTREE,
     ++	CONFIG_SCOPE_COMMAND,
     ++	CONFIG_SCOPE_SUBMODULE,
     ++};
     ++
     + struct git_config_source {
     + 	unsigned int use_stdin:1;
     + 	const char *file;
     + 	const char *blob;
     ++	enum config_scope scope;
     + };
     + 
     + enum config_origin_type {
     +@@
     + 
     + int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
     + 
     +-enum config_scope {
     +-	CONFIG_SCOPE_UNKNOWN = 0,
     +-	CONFIG_SCOPE_SYSTEM,
     +-	CONFIG_SCOPE_GLOBAL,
     +-	CONFIG_SCOPE_LOCAL,
     +-	CONFIG_SCOPE_WORKTREE,
     +-	CONFIG_SCOPE_COMMAND,
     +-};
     +-
     + enum config_scope current_config_scope(void);
     + const char *current_config_origin_type(void);
     + const char *current_config_name(void);
     +
     + diff --git a/submodule-config.c b/submodule-config.c
     + --- a/submodule-config.c
     + +++ b/submodule-config.c
     +@@
     + static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
     + {
     + 	if (repo->worktree) {
     +-		struct git_config_source config_source = { 0 };
     ++		struct git_config_source config_source = {
     ++			0, .scope = CONFIG_SCOPE_SUBMODULE
     ++		};
     + 		const struct config_options opts = { 0 };
     + 		struct object_id oid;
     + 		char *file;
     +
     + diff --git a/t/helper/test-config.c b/t/helper/test-config.c
     + --- a/t/helper/test-config.c
     + +++ b/t/helper/test-config.c
     +@@
     + 		return "repo";
     + 	case CONFIG_SCOPE_WORKTREE:
     + 		return "worktree";
     ++	case CONFIG_SCOPE_SUBMODULE:
     ++		return "submodule";
     + 	case CONFIG_SCOPE_COMMAND:
     +-		return "command";
     ++		return "cmdline";
     + 	default:
     + 		return "unknown";
     + 	}
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
     @@ -131,18 +299,17 @@
       	test_cmp expect output
       '
       
     -+
      +test_expect_success '--show-scope with --list' '
      +	cat >expect <<-EOF &&
     -+		(global)	user.global=true
     -+		(global)	user.override=global
     -+		(global)	include.path=$INCLUDE_DIR/absolute.include
     -+		(global)	user.absolute=include
     -+		(local)	user.local=true
     -+		(local)	user.override=local
     -+		(local)	include.path=../include/relative.include
     -+		(local)	user.relative=include
     -+		(command line)	user.cmdline=true
     ++		global	user.global=true
     ++		global	user.override=global
     ++		global	include.path=$INCLUDE_DIR/absolute.include
     ++		global	user.absolute=include
     ++		local	user.local=true
     ++		local	user.override=local
     ++		local	include.path=../include/relative.include
     ++		local	user.relative=include
     ++		command	user.cmdline=true
      +	EOF
      +	git -c user.cmdline=true config --list --show-scope >output &&
      +	test_cmp expect output
     @@ -151,16 +318,16 @@
      +test_expect_success !MINGW '--show-scope with --blob' '
      +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
      +	cat >expect <<-EOF &&
     -+		(command line)	user.custom=true
     ++		command	user.custom=true
      +	EOF
      +	git config --blob=$blob --show-scope --list >output &&
      +	test_cmp expect output
      +'
      +test_expect_success '--show-scope with --local' '
      +	cat >expect <<-\EOF &&
     -+		(local)	user.local=true
     -+		(local)	user.override=local
     -+		(local)	include.path=../include/relative.include
     ++		local	user.local=true
     ++		local	user.override=local
     ++		local	include.path=../include/relative.include
      +	EOF
      +	git config --local --list --show-scope >output &&
      +	test_cmp expect output
     @@ -168,15 +335,15 @@
      +
      +test_expect_success '--show-scope with --show-origin' '
      +	cat >expect <<-EOF &&
     -+		(global)	file:$HOME/.gitconfig	user.global=true
     -+		(global)	file:$HOME/.gitconfig	user.override=global
     -+		(global)	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     -+		(global)	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     -+		(local)	file:.git/config	user.local=true
     -+		(local)	file:.git/config	user.override=local
     -+		(local)	file:.git/config	include.path=../include/relative.include
     -+		(local)	file:.git/../include/relative.include	user.relative=include
     -+		(command line)	command line:	user.cmdline=true
     ++		global	file:$HOME/.gitconfig	user.global=true
     ++		global	file:$HOME/.gitconfig	user.override=global
     ++		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     ++		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     ++		local	file:.git/config	user.local=true
     ++		local	file:.git/config	user.override=local
     ++		local	file:.git/config	include.path=../include/relative.include
     ++		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 &&
      +	test_cmp expect output

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v2 1/4] config: fix typo in variable name
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
@ 2020-01-09 10:16   ` Matthew Rogers via GitGitGadget
  2020-01-09 19:07     ` Junio C Hamano
  2020-01-10 11:55     ` Jeff King
  2020-01-09 10:16   ` [PATCH v2 2/4] config: fix config scope enum Matthew Rogers via GitGitGadget
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v2 2/4] config: fix config scope enum
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
  2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-09 10:16   ` Matthew Rogers via GitGitGadget
  2020-01-09 19:06     ` Junio C Hamano
  2020-01-09 10:16   ` [PATCH v2 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases.

Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL
to reflect its new, more specific meaning.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 4 +++-
 upload-pack.c          | 3 ++-
 5 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..6695e463eb 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
+	case CONFIG_SCOPE_LOCAL:
 		return "repo";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v2 3/4] config: clarify meaning of command line scoping
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
  2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-09 10:16   ` [PATCH v2 2/4] config: fix config scope enum Matthew Rogers via GitGitGadget
@ 2020-01-09 10:16   ` Matthew Rogers via GitGitGadget
  2020-01-09 19:13     ` Junio C Hamano
  2020-01-09 10:16   ` [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  This is a little bit too specific
as there are other methods to pass config values so that the last for a
single command (namely --file and --blob).  As the "visibility" of config
values passed by these situations is common, we unify them as having a
scope of "command" rather than "command line".

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 6695e463eb..78bbb9eb98 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
                     ` (2 preceding siblings ...)
  2020-01-09 10:16   ` [PATCH v2 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-09 10:16   ` Matthew Rogers via GitGitGadget
  2020-01-09 19:50     ` Junio C Hamano
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++----
 builtin/config.c             | 56 ++++++++++++++++++++++++++++++++----
 config.c                     |  6 +++-
 config.h                     | 20 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       |  4 ++-
 t/t1300-config.sh            | 50 ++++++++++++++++++++++++++++++++
 7 files changed, 133 insertions(+), 22 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..2e47765aab 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value 
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..0367d28ec1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,41 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static const char *scope_to_string(enum config_scope scope) {
+	switch (scope) {
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
+static void show_config_scope(struct strbuf *buf) {
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +245,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_origin(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -599,6 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 	int nongit = !startup_info->have_repository;
 	char *value;
 
+
+
 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
 
 	argc = parse_options(argc, argv, prefix, builtin_config_options,
@@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..035fc8fb29 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
diff --git a/config.h b/config.h
index f383a71404..91f851e925 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,21 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +305,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 78bbb9eb98..aae2c6fc9e 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
 	case CONFIG_SCOPE_COMMAND:
-		return "command";
+		return "cmdline";
 	default:
 		return "unknown";
 	}
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..6cecc80b18 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1766,6 +1766,56 @@ test_expect_success !MINGW '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		global	user.global=true
+		global	user.override=global
+		global	include.path=$INCLUDE_DIR/absolute.include
+		global	user.absolute=include
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+		local	user.relative=include
+		command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		global	file:$HOME/.gitconfig	user.global=true
+		global	file:$HOME/.gitconfig	user.override=global
+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		local	file:.git/config	user.local=true
+		local	file:.git/config	user.override=local
+		local	file:.git/config	include.path=../include/relative.include
+		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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 2/4] config: fix config scope enum
  2020-01-09 10:16   ` [PATCH v2 2/4] config: fix config scope enum Matthew Rogers via GitGitGadget
@ 2020-01-09 19:06     ` Junio C Hamano
  2020-01-09 23:29       ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-09 19:06 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Previously when iterating through git config variables, worktree config
> and local config were both considered "CONFIG_SCOPE_REPO".  This was
> never a problem before as no one had needed to differentiate between the
> two cases.

Hmph, then "fix" on the title is a bit misleading, no?  

The enum may not have been as fine grained as you would have liked,
but if there was nothing broken, then we are doing this not to "fix"
anything.  

A more important thing to explain would probably be why we
(i.e. those who propose this change, those who give favoriable
reviews to it, and those who accept it change to the system) would
want to see finer-grained classification.  What do we expect to be
able to do with the resulting finer-grained set that we wouldn't be
able to with the original, and why is it a good thing?  That is what
readers of the proposed log message of this change would want to
see, I would think.

> Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL
> to reflect its new, more specific meaning.
>
> The clients of 'current_config_scope()' who cared about
> CONFIG_SCOPE_REPO are also modified to similarly care about
> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  config.c               | 7 ++-----
>  config.h               | 3 ++-
>  remote.c               | 3 ++-
>  t/helper/test-config.c | 4 +++-
>  upload-pack.c          | 3 ++-
>  5 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/config.c b/config.c
> index d75f88ca0c..447a013a15 100644
> --- a/config.c
> +++ b/config.c
> @@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
>  		ret += git_config_from_file(fn, user_config, data);
>  
> -	current_parsing_scope = CONFIG_SCOPE_REPO;
> +	current_parsing_scope = CONFIG_SCOPE_LOCAL;
>  	if (!opts->ignore_repo && repo_config &&
>  	    !access_or_die(repo_config, R_OK, 0))
>  		ret += git_config_from_file(fn, repo_config, data);
>  
> -	/*
> -	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
> -	 * But let's not complicate things before it's actually needed.
> -	 */
> +	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
>  	if (!opts->ignore_worktree && repository_format_worktree_config) {
>  		char *path = git_pathdup("config.worktree");
>  		if (!access_or_die(path, R_OK, 0))
> diff --git a/config.h b/config.h
> index 91fd4c5e96..284d92fb0e 100644
> --- a/config.h
> +++ b/config.h
> @@ -298,7 +298,8 @@ enum config_scope {
>  	CONFIG_SCOPE_UNKNOWN = 0,
>  	CONFIG_SCOPE_SYSTEM,
>  	CONFIG_SCOPE_GLOBAL,
> -	CONFIG_SCOPE_REPO,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
>  	CONFIG_SCOPE_CMDLINE,
>  };
>  
> diff --git a/remote.c b/remote.c
> index 5c4666b53a..593ce297ed 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
>  	}
>  	remote = make_remote(name, namelen);
>  	remote->origin = REMOTE_CONFIG;
> -	if (current_config_scope() == CONFIG_SCOPE_REPO)
> +	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
> +	current_config_scope() == CONFIG_SCOPE_WORKTREE)
>  		remote->configured_in_repo = 1;
>  	if (!strcmp(subkey, "mirror"))
>  		remote->mirror = git_config_bool(key, value);
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 214003d5b2..6695e463eb 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
>  		return "system";
>  	case CONFIG_SCOPE_GLOBAL:
>  		return "global";
> -	case CONFIG_SCOPE_REPO:
> +	case CONFIG_SCOPE_LOCAL:
>  		return "repo";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
>  	case CONFIG_SCOPE_CMDLINE:
>  		return "cmdline";
>  	default:
> diff --git a/upload-pack.c b/upload-pack.c
> index a00d7ece6b..c53249cac1 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
>  		precomposed_unicode = git_config_bool(var, value);
>  	}
>  
> -	if (current_config_scope() != CONFIG_SCOPE_REPO) {
> +	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
> +	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
>  		if (!strcmp("uploadpack.packobjectshook", var))
>  			return git_config_string(&pack_objects_hook, var, value);
>  	}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 1/4] config: fix typo in variable name
  2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-09 19:07     ` Junio C Hamano
  2020-01-09 23:22       ` Matt Rogers
  2020-01-10 11:55     ` Jeff King
  1 sibling, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-09 19:07 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> In git config use of the end_null variable to determine if we should be
> null terminating our output.  While it is correct to say a string is
> "null terminated" the character is actually the "nul" character, so this
> malapropism is being fixed.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  builtin/config.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

Obviously correct.

Malapropism is a new word in "git log" output in our history ;-)

> diff --git a/builtin/config.c b/builtin/config.c
> index 98d65bc0ad..52a904cfb1 100644
> --- a/builtin/config.c
> +++ b/builtin/config.c
> @@ -29,7 +29,7 @@ static int use_worktree_config;
>  static struct git_config_source given_config_source;
>  static int actions, type;
>  static char *default_value;
> -static int end_null;
> +static int end_nul;
>  static int respect_includes_opt = -1;
>  static struct config_options config_options;
>  static int show_origin;
> @@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
>  	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
>  	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
>  	OPT_GROUP(N_("Other")),
> -	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
> +	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
>  	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
>  	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
>  	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
> @@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
>  
>  static void show_config_origin(struct strbuf *buf)
>  {
> -	const char term = end_null ? '\0' : '\t';
> +	const char term = end_nul ? '\0' : '\t';
>  
>  	strbuf_addstr(buf, current_config_origin_type());
>  	strbuf_addch(buf, ':');
> -	if (end_null)
> +	if (end_nul)
>  		strbuf_addstr(buf, current_config_name());
>  	else
>  		quote_c_style(current_config_name(), buf, NULL, 0);
> @@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  		config_options.git_dir = get_git_dir();
>  	}
>  
> -	if (end_null) {
> +	if (end_nul) {
>  		term = '\0';
>  		delim = '\n';
>  		key_delim = '\n';

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 3/4] config: clarify meaning of command line scoping
  2020-01-09 10:16   ` [PATCH v2 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-09 19:13     ` Junio C Hamano
  2020-01-09 23:41       ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-09 19:13 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
> values passed in via the -c option.  This is a little bit too specific
> as there are other methods to pass config values so that the last for a
> single command (namely --file and --blob).

Sorry, but I cannot parse this, especially around "so that the last
for ..." part.

> As the "visibility" of config
> values passed by these situations is common, we unify them as having a
> scope of "command" rather than "command line".

Is the "unification" something done by this patch?  It does not
appear to be so.  The existing code already was using CMDLINE to
call "git -c VAR=VAL" and also something else (which is not clear to
me, unfortunately, probably because I failed to parse the above
X-<), and this step renames CMDLINE to COMMAND perhaps because
CMDLINE has too strong connotation with the "-c" thing and much less
with the other thing (which is not clear to me, unfortunately) and
you found that renaming it to COMMAND would cover both cases better?

I also do not get what you meant by "visibility", but it probably is
primarily because it is not clear what "the other thing" is.



> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  config.c               | 2 +-
>  config.h               | 2 +-
>  t/helper/test-config.c | 4 ++--
>  3 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/config.c b/config.c
> index 447a013a15..f319a3d6a0 100644
> --- a/config.c
> +++ b/config.c
> @@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  		free(path);
>  	}
>  
> -	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
> +	current_parsing_scope = CONFIG_SCOPE_COMMAND;
>  	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
>  		die(_("unable to parse command-line config"));
>  
> diff --git a/config.h b/config.h
> index 284d92fb0e..f383a71404 100644
> --- a/config.h
> +++ b/config.h
> @@ -300,7 +300,7 @@ enum config_scope {
>  	CONFIG_SCOPE_GLOBAL,
>  	CONFIG_SCOPE_LOCAL,
>  	CONFIG_SCOPE_WORKTREE,
> -	CONFIG_SCOPE_CMDLINE,
> +	CONFIG_SCOPE_COMMAND,
>  };
>  
>  enum config_scope current_config_scope(void);
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 6695e463eb..78bbb9eb98 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
>  		return "repo";
>  	case CONFIG_SCOPE_WORKTREE:
>  		return "worktree";
> -	case CONFIG_SCOPE_CMDLINE:
> -		return "cmdline";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
>  	default:
>  		return "unknown";
>  	}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-09 10:16   ` [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-09 19:50     ` Junio C Hamano
  2020-01-09 23:47       ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-09 19:50 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> When a user queries config values with --show-origin, often it's
> difficult to determine what the actual "scope" (local, global, etc.) of
> a given value is based on just the origin file.
>
> Teach 'git config' the '--show-scope' option to print the scope of all
> displayed config values.  Note that we should never see anything of
> "submodule" scope as that is only ever used by submodule-config.c when
> parsing the '.gitmodules' file.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  Documentation/git-config.txt | 15 ++++++----
>  builtin/config.c             | 56 ++++++++++++++++++++++++++++++++----
>  config.c                     |  6 +++-
>  config.h                     | 20 +++++++------
>  submodule-config.c           |  4 ++-
>  t/helper/test-config.c       |  4 ++-
>  t/t1300-config.sh            | 50 ++++++++++++++++++++++++++++++++
>  7 files changed, 133 insertions(+), 22 deletions(-)
>
> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
> index 899e92a1c9..2e47765aab 100644
> --- a/Documentation/git-config.txt
> +++ b/Documentation/git-config.txt
> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options
>  SYNOPSIS
>  --------
>  [verse]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
>  'git config' [<file-option>] [--type=<type>] --add name value
>  'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
>  'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
>  'git config' [<file-option>] --unset name [value_regex]
>  'git config' [<file-option>] --unset-all name [value_regex]
>  'git config' [<file-option>] --rename-section old_name new_name
>  'git config' [<file-option>] --remove-section name
> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
> +'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
> @@ -222,6 +222,11 @@ Valid `<type>`'s include:
>  	the actual origin (config file path, ref, or blob id if
>  	applicable).
>  
> +--show-scope::
> +	Similar to `--show-origin` in that it augments the output of
> +	all queried config options with the scope of that value 
> +	(local, global, system, command).
> +
>  --get-colorbool name [stdout-is-tty]::
>  
>  	Find the color setting for `name` (e.g. `color.diff`) and output
> diff --git a/builtin/config.c b/builtin/config.c
> index 52a904cfb1..0367d28ec1 100644
> --- a/builtin/config.c
> +++ b/builtin/config.c
> @@ -33,6 +33,7 @@ static int end_nul;
>  static int respect_includes_opt = -1;
>  static struct config_options config_options;
>  static int show_origin;
> +static int show_scope;
>  
>  #define ACTION_GET (1<<0)
>  #define ACTION_GET_ALL (1<<1)
> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
>  	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
>  	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
>  	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
> +	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
>  	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
>  	OPT_END(),
>  };
> @@ -189,11 +191,41 @@ static void show_config_origin(struct strbuf *buf)
>  	strbuf_addch(buf, term);
>  }
>  
> +static const char *scope_to_string(enum config_scope scope) {

Style: the outermost opening and closing parentheses of a functiond
definition sit on their own lines by themselves.  Same for the next
one.

> +	switch (scope) {
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
> +	default:
> +		return "unknown";

Makes me wonder if this wants to be done via a table, which would
later allow a parser to map in the other direction, taking a string
and returning the corresponding enum, more easily (imagine a yet to
be invented feature to "list config settings for only this scope").

> +	}
> +}
> +
> +static void show_config_scope(struct strbuf *buf) {
> +	const char term = end_nul ? '\0' : '\t';
> +	const char *scope = scope_to_string(current_config_scope());
> +
> +	strbuf_addstr(buf, N_(scope));
> +	strbuf_addch(buf, term);
> +}
> +
>  static int show_all_config(const char *key_, const char *value_, void *cb)
>  {
> -	if (show_origin) {
> +	if (show_origin || show_scope) {
>  		struct strbuf buf = STRBUF_INIT;
> -		show_config_origin(&buf);
> +		if (show_scope)
> +			show_config_scope(&buf);
> +		if (show_origin)
> +			show_config_origin(&buf);
>  		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
>  		fwrite(buf.buf, 1, buf.len, stdout);
>  		strbuf_release(&buf);
> @@ -213,6 +245,8 @@ struct strbuf_list {
>  
>  static int format_config(struct strbuf *buf, const char *key_, const char *value_)
>  {
> +	if (show_scope)
> +		show_config_origin(buf);
>  	if (show_origin)
>  		show_config_origin(buf);

Shouldn't one of these show scope instead of origin?  I wonder how
the tests I see later in the patch could have passed with this.

>  	if (show_keys)
> @@ -599,6 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  	int nongit = !startup_info->have_repository;
>  	char *value;
>  
> +
> +

Unnecessary edit?

>  	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
>  
>  	argc = parse_options(argc, argv, prefix, builtin_config_options,
> @@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  			!strcmp(given_config_source.file, "-")) {
>  		given_config_source.file = NULL;
>  		given_config_source.use_stdin = 1;
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;
>  	}
>  
>  	if (use_global_config) {
> @@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  			 */
>  			die(_("$HOME not set"));
>  
> +		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
> +
>  		if (access_or_warn(user_config, R_OK, 0) &&
>  		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
>  			given_config_source.file = xdg_config;
> @@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  			free(xdg_config);
>  		}
>  	}
> -	else if (use_system_config)
> +	else if (use_system_config) {
>  		given_config_source.file = git_etc_gitconfig();
> -	else if (use_local_config)
> +		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
> +	} else if (use_local_config) {
>  		given_config_source.file = git_pathdup("config");
> -	else if (use_worktree_config) {
> +		given_config_source.scope = CONFIG_SCOPE_LOCAL;
> +	} else if (use_worktree_config) {
>  		struct worktree **worktrees = get_worktrees(0);
>  		if (repository_format_worktree_config)
>  			given_config_source.file = git_pathdup("config.worktree");
> @@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>  			      "section in \"git help worktree\" for details"));
>  		else
>  			given_config_source.file = git_pathdup("config");
> +		given_config_source.scope = CONFIG_SCOPE_LOCAL;
>  		free_worktrees(worktrees);
>  	} else if (given_config_source.file) {
>  		if (!is_absolute_path(given_config_source.file) && prefix)
>  			given_config_source.file =
>  				prefix_filename(prefix, given_config_source.file);
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;
> +	} else if (given_config_source.blob) {
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;

These that set scope for individual sources, not just during the
normal sequence, are new in this round, and I think it is an
improvement.

>  	}
>  
> +
>  	if (respect_includes_opt == -1)
>  		config_options.respect_includes = !given_config_source.file;
>  	else
> diff --git a/config.c b/config.c
> index f319a3d6a0..035fc8fb29 100644
> --- a/config.c
> +++ b/config.c
> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	char *xdg_config = xdg_config_home("config");
>  	char *user_config = expand_user_path("~/.gitconfig", 0);
>  	char *repo_config;
> +	enum config_scope prev_parsing_scope = current_parsing_scope;
>  
>  	if (opts->commondir)
>  		repo_config = mkpathdup("%s/config", opts->commondir);
> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
>  		die(_("unable to parse command-line config"));
>  
> -	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
> +	current_parsing_scope = prev_parsing_scope;
>  	free(xdg_config);
>  	free(user_config);
>  	free(repo_config);
> @@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
>  		data = &inc;
>  	}
>  
> +	if (config_source)
> +		current_parsing_scope = config_source->scope;
> +
>  	/*
>  	 * If we have a specific filename, use it. Otherwise, follow the
>  	 * regular lookup sequence.
> diff --git a/config.h b/config.h
> index f383a71404..91f851e925 100644
> --- a/config.h
> +++ b/config.h
> @@ -35,10 +35,21 @@ struct object_id;
>  
>  #define CONFIG_REGEX_NONE ((void *)1)
>  
> +enum config_scope {
> +	CONFIG_SCOPE_UNKNOWN = 0,
> +	CONFIG_SCOPE_SYSTEM,
> +	CONFIG_SCOPE_GLOBAL,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
> +	CONFIG_SCOPE_COMMAND,
> +	CONFIG_SCOPE_SUBMODULE,
> +};
> +
>  struct git_config_source {
>  	unsigned int use_stdin:1;
>  	const char *file;
>  	const char *blob;
> +	enum config_scope scope;
>  };
>  
>  enum config_origin_type {
> @@ -294,15 +305,6 @@ int config_error_nonbool(const char *);
>  
>  int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
>  
> -enum config_scope {
> -	CONFIG_SCOPE_UNKNOWN = 0,
> -	CONFIG_SCOPE_SYSTEM,
> -	CONFIG_SCOPE_GLOBAL,
> -	CONFIG_SCOPE_LOCAL,
> -	CONFIG_SCOPE_WORKTREE,
> -	CONFIG_SCOPE_COMMAND,
> -};
> -
>  enum config_scope current_config_scope(void);
>  const char *current_config_origin_type(void);
>  const char *current_config_name(void);
> diff --git a/submodule-config.c b/submodule-config.c
> index 85064810b2..b8e97d8ae8 100644
> --- a/submodule-config.c
> +++ b/submodule-config.c
> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
>  static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
>  {
>  	if (repo->worktree) {
> -		struct git_config_source config_source = { 0 };
> +		struct git_config_source config_source = {
> +			0, .scope = CONFIG_SCOPE_SUBMODULE
> +		};
>  		const struct config_options opts = { 0 };
>  		struct object_id oid;
>  		char *file;
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 78bbb9eb98..aae2c6fc9e 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)
>  		return "repo";
>  	case CONFIG_SCOPE_WORKTREE:
>  		return "worktree";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
>  	case CONFIG_SCOPE_COMMAND:
> -		return "command";
> +		return "cmdline";

Oh???

>  	default:
>  		return "unknown";
>  	}
> diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> index 983a0a1583..6cecc80b18 100755
> --- a/t/t1300-config.sh
> +++ b/t/t1300-config.sh
> @@ -1766,6 +1766,56 @@ test_expect_success !MINGW '--show-origin blob ref' '
>  	test_cmp expect output
>  '
>  
> +test_expect_success '--show-scope with --list' '
> +	cat >expect <<-EOF &&
> +		global	user.global=true
> +		global	user.override=global
> +		global	include.path=$INCLUDE_DIR/absolute.include
> +		global	user.absolute=include
> +		local	user.local=true
> +		local	user.override=local
> +		local	include.path=../include/relative.include
> +		local	user.relative=include
> +		command	user.cmdline=true
> +	EOF
> +	git -c user.cmdline=true config --list --show-scope >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success !MINGW '--show-scope with --blob' '
> +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
> +	cat >expect <<-EOF &&
> +		command	user.custom=true
> +	EOF
> +	git config --blob=$blob --show-scope --list >output &&
> +	test_cmp expect output
> +'
> +test_expect_success '--show-scope with --local' '
> +	cat >expect <<-\EOF &&
> +		local	user.local=true
> +		local	user.override=local
> +		local	include.path=../include/relative.include
> +	EOF
> +	git config --local --list --show-scope >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success '--show-scope with --show-origin' '
> +	cat >expect <<-EOF &&
> +		global	file:$HOME/.gitconfig	user.global=true
> +		global	file:$HOME/.gitconfig	user.override=global
> +		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
> +		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
> +		local	file:.git/config	user.local=true
> +		local	file:.git/config	user.override=local
> +		local	file:.git/config	include.path=../include/relative.include
> +		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 &&
> +	test_cmp expect output
> +'
> +
>  test_expect_success '--local requires a repo' '
>  	# we expect 128 to ensure that we do not simply
>  	# fail to find anything and return code "1"

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 1/4] config: fix typo in variable name
  2020-01-09 19:07     ` Junio C Hamano
@ 2020-01-09 23:22       ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-09 23:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

>
> Malapropism is a new word in "git log" output in our history ;-)
>

Yeah, I remember my coworker saying that to me the day I wrote the
message and it was just stuck in my head

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 2/4] config: fix config scope enum
  2020-01-09 19:06     ` Junio C Hamano
@ 2020-01-09 23:29       ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-09 23:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

On Thu, Jan 9, 2020 at 2:06 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Matthew Rogers <mattr94@gmail.com>
> >
> > Previously when iterating through git config variables, worktree config
> > and local config were both considered "CONFIG_SCOPE_REPO".  This was
> > never a problem before as no one had needed to differentiate between the
> > two cases.
>
> Hmph, then "fix" on the title is a bit misleading, no?
>
> The enum may not have been as fine grained as you would have liked,
> but if there was nothing broken, then we are doing this not to "fix"
> anything.
>

I see where you're coming from, but I would definitely consider this a "fix"
in that it's something that (as explained in the deleted comment) should
have been this way from the start but was unnecessary as no one had a
need for it yet.  But I definitely wouldn't be against changing the phrasing
to something like "clean up" or whatever your preferred wording would be.

> A more important thing to explain would probably be why we
> (i.e. those who propose this change, those who give favoriable
> reviews to it, and those who accept it change to the system) would
> want to see finer-grained classification.  What do we expect to be
> able to do with the resulting finer-grained set that we wouldn't be
> able to with the original, and why is it a good thing?  That is what
> readers of the proposed log message of this change would want to
> see, I would think.
>

This is really more prep for patch 4 later on in this series, as a user who
ran the proposed '--show-scope' later on in the series would care what
was "worktree" vs "local".

Regardless, I think the two options I have would be to amend the commit
message with that extra information or roll it together with patch 4

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 3/4] config: clarify meaning of command line scoping
  2020-01-09 19:13     ` Junio C Hamano
@ 2020-01-09 23:41       ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-09 23:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

On Thu, Jan 9, 2020 at 2:14 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Matthew Rogers <mattr94@gmail.com>
> >
> > CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
> > values passed in via the -c option.  This is a little bit too specific
> > as there are other methods to pass config values so that the last for a
> > single command (namely --file and --blob).
>
> Sorry, but I cannot parse this, especially around "so that the last
> for ..." part.
>

My bad, I guess I must have not read as carefully as I thought I did.
It should read:
"... there are other methods to pass config values so that _they_ last
for a single command ..."

> > As the "visibility" of config
> > values passed by these situations is common, we unify them as having a
> > scope of "command" rather than "command line".
>
> Is the "unification" something done by this patch?  It does not
> appear to be so.  The existing code already was using CMDLINE to
> call "git -c VAR=VAL" and also something else (which is not clear to
> me, unfortunately, probably because I failed to parse the above
> X-<), and this step renames CMDLINE to COMMAND perhaps because
> CMDLINE has too strong connotation with the "-c" thing and much less
> with the other thing (which is not clear to me, unfortunately) and
> you found that renaming it to COMMAND would cover both cases better?

Essentially, the "unification" was referring to more the unification of all the
things that affect configuration only for the duration of a specific command.

The gist of this patch was to say "There are a few ways besides -c to pass
a configuration option that lasts for a single command, so it makes sense
to broaden that scope.".  The change is definitely justified in that COMMAND
communicates that much clearer than CMDLINE as REPO, GLOBAL, SYSTEM
all describe the thing that can see the configuration options, and
it's specifically the
command the can see the -c options and not the command line as a whole.

>
> I also do not get what you meant by "visibility", but it probably is
> primarily because it is not clear what "the other thing" is.

I was using visibility as another way to conceptualize scoping.  A
scope more or less determines who can "see" a thing, so maybe that
language was a little bit too much in my head.

The issue is that currently the code doesn't care about any of that (as only -c
options actually have COMMAND scoping), so maybe I should roll it into the
next patch of the series?  As that introduces code that actually cares about the
difference?

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-09 19:50     ` Junio C Hamano
@ 2020-01-09 23:47       ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-09 23:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

> > +     switch (scope) {
> > +     case CONFIG_SCOPE_LOCAL:
> > +             return "local";
> > +     case CONFIG_SCOPE_GLOBAL:
> > +             return "global";
> > +     case CONFIG_SCOPE_SYSTEM:
> > +             return "system";
> > +     case CONFIG_SCOPE_WORKTREE:
> > +             return "worktree";
> > +     case CONFIG_SCOPE_COMMAND:
> > +             return "command";
> > +     case CONFIG_SCOPE_SUBMODULE:
> > +             return "submodule";
> > +     default:
> > +             return "unknown";
>
> Makes me wonder if this wants to be done via a table, which would
> later allow a parser to map in the other direction, taking a string
> and returning the corresponding enum, more easily (imagine a yet to
> be invented feature to "list config settings for only this scope").

I was thinking the same but then I realized such an option already exists,
--local and company.

>
> > +     }
> > +}
> > +
> > +static void show_config_scope(struct strbuf *buf) {
> > +     const char term = end_nul ? '\0' : '\t';
> > +     const char *scope = scope_to_string(current_config_scope());
> > +
> > +     strbuf_addstr(buf, N_(scope));
> > +     strbuf_addch(buf, term);
> > +}
> > +
> >  static int show_all_config(const char *key_, const char *value_, void *cb)
> >  {
> > -     if (show_origin) {
> > +     if (show_origin || show_scope) {
> >               struct strbuf buf = STRBUF_INIT;
> > -             show_config_origin(&buf);
> > +             if (show_scope)
> > +                     show_config_scope(&buf);
> > +             if (show_origin)
> > +                     show_config_origin(&buf);
> >               /* Use fwrite as "buf" can contain \0's if "end_null" is set. */
> >               fwrite(buf.buf, 1, buf.len, stdout);
> >               strbuf_release(&buf);
> > @@ -213,6 +245,8 @@ struct strbuf_list {
> >
> >  static int format_config(struct strbuf *buf, const char *key_, const char *value_)
> >  {
> > +     if (show_scope)
> > +             show_config_origin(buf);
> >       if (show_origin)
> >               show_config_origin(buf);
>
> Shouldn't one of these show scope instead of origin?  I wonder how
> the tests I see later in the patch could have passed with this.
>

Oof, that was a blunder... I think this passes the tests because none of them
actually hits `format_config()` only `show_all_config()` so I'll definitely add
a test case for this. (and fix it while I'm at it)

> > diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> > index 78bbb9eb98..aae2c6fc9e 100644
> > --- a/t/helper/test-config.c
> > +++ b/t/helper/test-config.c
> > @@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)
> >               return "repo";
> >       case CONFIG_SCOPE_WORKTREE:
> >               return "worktree";
> > +     case CONFIG_SCOPE_SUBMODULE:
> > +             return "submodule";
> >       case CONFIG_SCOPE_COMMAND:
> > -             return "command";
> > +             return "cmdline";
>
> Oh???
>

I definitely got a little too excited to get this patch in, so I
definitely apologize for that,
but thanks for the review.

-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v2 1/4] config: fix typo in variable name
  2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-09 19:07     ` Junio C Hamano
@ 2020-01-10 11:55     ` Jeff King
  1 sibling, 0 replies; 98+ messages in thread
From: Jeff King @ 2020-01-10 11:55 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

On Thu, Jan 09, 2020 at 10:16:38AM +0000, Matthew Rogers via GitGitGadget wrote:

> -	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
> +	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),

The user-facing option is still spelled "null". Obviously we can't just
change that, but if we are trying to prefer "nul", should we offer both?

I think we actually _do_ allow "--nul" because of parse-option's
willingness to accept a partial name. But if we wanted to advertise one
over the other in "-h", then we'd have to set up the alias ourselves.

Interestingly, "xargs" (and GNU grep) spells it as "--null", so perhaps
that's an argument to keep it as-is. Likewise if we accept that "null
termination" is a correct name, I suppose.

-Peff

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v3 0/4] config: allow user to know scope of config options
  2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
                     ` (3 preceding siblings ...)
  2020-01-09 10:16   ` [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-17 15:31   ` Matthew Rogers via GitGitGadget
  2020-01-17 15:31     ` [PATCH v3 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
                       ` (4 more replies)
  4 siblings, 5 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-17 15:31 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v2:

 * Redid commit messages for content/clarity
 * Minor fixes around using --show-scope with a single value (format_config)

Matthew Rogers (4):
  config: fix typo in variable name
  config: refine config scope enum
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt | 15 +++++---
 builtin/config.c             | 66 ++++++++++++++++++++++++++++++------
 config.c                     | 15 ++++----
 config.h                     | 19 ++++++-----
 remote.c                     |  3 +-
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       | 10 ++++--
 t/t1300-config.sh            | 58 +++++++++++++++++++++++++++++++
 t/t1308-config-set.sh        |  2 +-
 upload-pack.c                |  3 +-
 10 files changed, 158 insertions(+), 37 deletions(-)


base-commit: 232378479ee6c66206d47a9be175e3a39682aea6
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v2:

 1:  b40480f03a = 1:  f5a81a4d25 config: fix typo in variable name
 2:  e8e05f3940 ! 2:  f06f9291b7 config: fix config scope enum
     @@ -1,14 +1,21 @@
      Author: Matthew Rogers <mattr94@gmail.com>
      
     -    config: fix config scope enum
     +    config: refine config scope enum
      
          Previously when iterating through git config variables, worktree config
          and local config were both considered "CONFIG_SCOPE_REPO".  This was
          never a problem before as no one had needed to differentiate between the
     -    two cases.
     +    two cases, but future functionality may care whether or not the config
     +    options come from a worktree or from the repository's actual local
     +    config file.  For example, the planned feature to add a '--show-scope'
     +    to config to allow a user to see which scope listed config options come
     +    from would confuse users if it just printed 'repo' rather than 'local'
     +    or 'worktree' as the documentation would lead them to expect.  As well
     +    as the additional benefit of making the implementation look more like
     +    how the documentation describes the interface.
      
     -    Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL
     -    to reflect its new, more specific meaning.
     +    To accomplish this we split out what was previously considered repo
     +    scope to be local and worktree.
      
          The clients of 'current_config_scope()' who cared about
          CONFIG_SCOPE_REPO are also modified to similarly care about
     @@ -82,6 +89,19 @@
       		return "cmdline";
       	default:
      
     + diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
     + --- a/t/t1308-config-set.sh
     + +++ b/t/t1308-config-set.sh
     +@@
     + 	value=from-cmdline
     + 	origin=command line
     + 	name=
     +-	scope=cmdline
     ++	scope=command
     + 	EOF
     + 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
     + 	test_cmp expect actual
     +
       diff --git a/upload-pack.c b/upload-pack.c
       --- a/upload-pack.c
       +++ b/upload-pack.c
 3:  8225273546 ! 3:  97b8a7641d config: clarify meaning of command line scoping
     @@ -3,11 +3,13 @@
          config: clarify meaning of command line scoping
      
          CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
     -    values passed in via the -c option.  This is a little bit too specific
     -    as there are other methods to pass config values so that the last for a
     -    single command (namely --file and --blob).  As the "visibility" of config
     -    values passed by these situations is common, we unify them as having a
     -    scope of "command" rather than "command line".
     +    values passed in via the -c option.  Options passed in using this
     +    mechanism share similar scoping characteristics with the --file and
     +    --blob options of the 'config' command, namely that they are only in use
     +    for that single invocation of git, and that they supersede the normal
     +    system/global/local hierarchy.  This patch introduces
     +    CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
     +    CONFIG_SCOPE_CMDLINE redundant.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
      
 4:  92ce9b7824 ! 4:  61ff3c64b5 config: add '--show-scope' to print the scope of a config value
     @@ -76,7 +76,8 @@
       	strbuf_addch(buf, term);
       }
       
     -+static const char *scope_to_string(enum config_scope scope) {
     ++static const char *scope_to_string(enum config_scope scope)
     ++{
      +	switch (scope) {
      +	case CONFIG_SCOPE_LOCAL:
      +		return "local";
     @@ -95,7 +96,8 @@
      +	}
      +}
      +
     -+static void show_config_scope(struct strbuf *buf) {
     ++static void show_config_scope(struct strbuf *buf)
     ++{
      +	const char term = end_nul ? '\0' : '\t';
      +	const char *scope = scope_to_string(current_config_scope());
      +
     @@ -121,19 +123,10 @@
       static int format_config(struct strbuf *buf, const char *key_, const char *value_)
       {
      +	if (show_scope)
     -+		show_config_origin(buf);
     ++		show_config_scope(buf);
       	if (show_origin)
       		show_config_origin(buf);
       	if (show_keys)
     -@@
     - 	int nongit = !startup_info->have_repository;
     - 	char *value;
     - 
     -+
     -+
     - 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
     - 
     - 	argc = parse_options(argc, argv, prefix, builtin_config_options,
      @@
       			!strcmp(given_config_source.file, "-")) {
       		given_config_source.file = NULL;
     @@ -286,11 +279,8 @@
      +	case CONFIG_SCOPE_SUBMODULE:
      +		return "submodule";
       	case CONFIG_SCOPE_COMMAND:
     --		return "command";
     -+		return "cmdline";
     + 		return "command";
       	default:
     - 		return "unknown";
     - 	}
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
     @@ -333,6 +323,14 @@
      +	test_cmp expect output
      +'
      +
     ++test_expect_success '--show-scope getting a single value' '
     ++	cat >expect <<-\EOF &&
     ++		local	true
     ++	EOF
     ++	git config --show-scope --get user.local >output &&
     ++	test_cmp expect output
     ++'
     ++
      +test_expect_success '--show-scope with --show-origin' '
      +	cat >expect <<-EOF &&
      +		global	file:$HOME/.gitconfig	user.global=true

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v3 1/4] config: fix typo in variable name
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
@ 2020-01-17 15:31     ` Matthew Rogers via GitGitGadget
  2020-01-17 15:31     ` [PATCH v3 2/4] config: refine config scope enum Matthew Rogers via GitGitGadget
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-17 15:31 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v3 2/4] config: refine config scope enum
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-17 15:31     ` [PATCH v3 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-17 15:31     ` Matthew Rogers via GitGitGadget
  2020-01-17 20:44       ` Junio C Hamano
  2020-01-17 15:31     ` [PATCH v3 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-17 15:31 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases, but future functionality may care whether or not the config
options come from a worktree or from the repository's actual local
config file.  For example, the planned feature to add a '--show-scope'
to config to allow a user to see which scope listed config options come
from would confuse users if it just printed 'repo' rather than 'local'
or 'worktree' as the documentation would lead them to expect.  As well
as the additional benefit of making the implementation look more like
how the documentation describes the interface.

To accomplish this we split out what was previously considered repo
scope to be local and worktree.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 4 +++-
 t/t1308-config-set.sh  | 2 +-
 upload-pack.c          | 3 ++-
 6 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..6695e463eb 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
+	case CONFIG_SCOPE_LOCAL:
 		return "repo";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7b4e1a63eb..535b2a73f7 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=cmdline
+	scope=command
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v3 3/4] config: clarify meaning of command line scoping
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-17 15:31     ` [PATCH v3 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-17 15:31     ` [PATCH v3 2/4] config: refine config scope enum Matthew Rogers via GitGitGadget
@ 2020-01-17 15:31     ` Matthew Rogers via GitGitGadget
  2020-01-17 21:00       ` Junio C Hamano
  2020-01-17 15:31     ` [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-17 15:31 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  Options passed in using this
mechanism share similar scoping characteristics with the --file and
--blob options of the 'config' command, namely that they are only in use
for that single invocation of git, and that they supersede the normal
system/global/local hierarchy.  This patch introduces
CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
CONFIG_SCOPE_CMDLINE redundant.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 6695e463eb..78bbb9eb98 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                       ` (2 preceding siblings ...)
  2020-01-17 15:31     ` [PATCH v3 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-17 15:31     ` Matthew Rogers via GitGitGadget
  2020-01-17 21:21       ` Junio C Hamano
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  4 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-17 15:31 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++----
 builtin/config.c             | 56 ++++++++++++++++++++++++++++++----
 config.c                     |  6 +++-
 config.h                     | 20 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       |  2 ++
 t/t1300-config.sh            | 58 ++++++++++++++++++++++++++++++++++++
 7 files changed, 140 insertions(+), 21 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..2e47765aab 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value 
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..d5931061e8 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static const char *scope_to_string(enum config_scope scope)
+{
+	switch (scope) {
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +247,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..035fc8fb29 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
diff --git a/config.h b/config.h
index f383a71404..91f851e925 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,21 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +305,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 78bbb9eb98..c93bee15c3 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,6 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
 	case CONFIG_SCOPE_COMMAND:
 		return "command";
 	default:
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..b654a6d2f9 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		global	user.global=true
+		global	user.override=global
+		global	include.path=$INCLUDE_DIR/absolute.include
+		global	user.absolute=include
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+		local	user.relative=include
+		command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope getting a single value' '
+	cat >expect <<-\EOF &&
+		local	true
+	EOF
+	git config --show-scope --get user.local >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		global	file:$HOME/.gitconfig	user.global=true
+		global	file:$HOME/.gitconfig	user.override=global
+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		local	file:.git/config	user.local=true
+		local	file:.git/config	user.override=local
+		local	file:.git/config	include.path=../include/relative.include
+		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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 2/4] config: refine config scope enum
  2020-01-17 15:31     ` [PATCH v3 2/4] config: refine config scope enum Matthew Rogers via GitGitGadget
@ 2020-01-17 20:44       ` Junio C Hamano
  2020-01-18 15:27         ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-17 20:44 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/config.h b/config.h
> index 91fd4c5e96..284d92fb0e 100644
> --- a/config.h
> +++ b/config.h
> @@ -298,7 +298,8 @@ enum config_scope {
>  	CONFIG_SCOPE_UNKNOWN = 0,
>  	CONFIG_SCOPE_SYSTEM,
>  	CONFIG_SCOPE_GLOBAL,
> -	CONFIG_SCOPE_REPO,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
>  	CONFIG_SCOPE_CMDLINE,
>  };

So the gist of the change is to split REPO into two, LOCAL and
WORKTREE.

If we can find a way to state that concisely, perhaps we can improve
"refine enum" and make it more informative.

> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 214003d5b2..6695e463eb 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
>  		return "system";
>  	case CONFIG_SCOPE_GLOBAL:
>  		return "global";
> -	case CONFIG_SCOPE_REPO:
> +	case CONFIG_SCOPE_LOCAL:
>  		return "repo";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
>  	case CONFIG_SCOPE_CMDLINE:
>  		return "cmdline";
>  	default:
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 7b4e1a63eb..535b2a73f7 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-cmdline
>  	origin=command line
>  	name=
> -	scope=cmdline
> +	scope=command

Why???

>  	EOF
>  	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
>  	test_cmp expect actual
> diff --git a/upload-pack.c b/upload-pack.c
> index a00d7ece6b..c53249cac1 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
>  		precomposed_unicode = git_config_bool(var, value);
>  	}
>  
> -	if (current_config_scope() != CONFIG_SCOPE_REPO) {
> +	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
> +	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
>  		if (!strcmp("uploadpack.packobjectshook", var))
>  			return git_config_string(&pack_objects_hook, var, value);
>  	}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 3/4] config: clarify meaning of command line scoping
  2020-01-17 15:31     ` [PATCH v3 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-17 21:00       ` Junio C Hamano
  2020-01-18 15:33         ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-17 21:00 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
> values passed in via the -c option.  Options passed in using this
> mechanism share similar scoping characteristics with the --file and
> --blob options of the 'config' command, namely that they are only in use
> for that single invocation of git, and that they supersede the normal
> system/global/local hierarchy.  

All of the above justifies why it makes sense to treat --file,
--blob and "git -c VAR=VAL" as the same scope (i.e. it would have
been a nice part of log message of the commit that introduced
SCOPE_CMDLINE), but that is not something we need to justify
now---we have such a scope for one-shot settings and these three
sources are already treated as the same class.

> This patch introduces
> CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
> CONFIG_SCOPE_CMDLINE redundant.

The change in this commit is to rename CMDLINE to COMMAND.  That is
what the proposed log message for this step must justify.

	We internally use CONFIG_SCOPE_CMDLINE for the scope for the
	configuration variables that come from "git -c VAR=VAL",
	"git config --file=FILE" and "git config --blob=BLOB".  As
	we are going to expose the scope names to end-users in the
	next step, let's rethink the half-cryptic "cmdline" and
	instead use a proper word "command" (the settings from three
	sources in this scope are all in effect only during a single
	invocation of a git command).

or something like that.


> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
>  		return "repo";
>  	case CONFIG_SCOPE_WORKTREE:
>  		return "worktree";
> -	case CONFIG_SCOPE_CMDLINE:
> -		return "cmdline";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";

The only externally observable effect of this patch is this output
string from test-tool and we are not breaking end-user experience,
but I am not sure if this churn is worth it.  I dunno.

In any case, the change to t1308 we saw in the previous step belongs
to this step, I think.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-17 15:31     ` [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-17 21:21       ` Junio C Hamano
  2020-01-17 21:26         ` Bert Wesarg
  2020-01-18 15:42         ` Matt Rogers
  0 siblings, 2 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-17 21:21 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +--show-scope::
> +	Similar to `--show-origin` in that it augments the output of
> +	all queried config options with the scope of that value 
> +	(local, global, system, command).
> +
>  --get-colorbool name [stdout-is-tty]::
>  
>  	Find the color setting for `name` (e.g. `color.diff`) and output
> diff --git a/builtin/config.c b/builtin/config.c
> index 52a904cfb1..d5931061e8 100644
> --- a/builtin/config.c
> +++ b/builtin/config.c
> @@ -33,6 +33,7 @@ static int end_nul;
>  static int respect_includes_opt = -1;
>  static struct config_options config_options;
>  static int show_origin;
> +static int show_scope;
>  
>  #define ACTION_GET (1<<0)
>  #define ACTION_GET_ALL (1<<1)
> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
>  	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
>  	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
>  	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
> +	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
>  	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
>  	OPT_END(),
>  };
> @@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)
>  	strbuf_addch(buf, term);
>  }
>  
> +static const char *scope_to_string(enum config_scope scope)
> +{
> +	switch (scope) {
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
> +	default:
> +		return "unknown";
> +	}
> +}

It is a shame that with this defined in the main part of the system
test-tool still needs to carry its own private copy.

I wonder if it results in a better system if we rename this to

	const char *config_scope_name(enum config_scope scope)

made it externally visible, and use it in t/helper/test-config.c
and get rid of the private copy scope_name() there?

> diff --git a/config.h b/config.h
> index f383a71404..91f851e925 100644
> --- a/config.h
> +++ b/config.h
> @@ -35,10 +35,21 @@ struct object_id;
>  
>  #define CONFIG_REGEX_NONE ((void *)1)
>  
> +enum config_scope {
> +	CONFIG_SCOPE_UNKNOWN = 0,
> +	CONFIG_SCOPE_SYSTEM,
> +	CONFIG_SCOPE_GLOBAL,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
> +	CONFIG_SCOPE_COMMAND,
> +	CONFIG_SCOPE_SUBMODULE,
> +};
> +

And this is the logical place to make an external definition, if we
were to go that route.

> diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> index 983a0a1583..b654a6d2f9 100755
> --- a/t/t1300-config.sh
> +++ b/t/t1300-config.sh
> @@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '
>  	test_cmp expect output
>  '
>  
> +test_expect_success '--show-scope with --list' '
> +	cat >expect <<-EOF &&
> +		global	user.global=true
> +		global	user.override=global
> +		global	include.path=$INCLUDE_DIR/absolute.include
> +		global	user.absolute=include
> +		local	user.local=true
> +		local	user.override=local
> +		local	include.path=../include/relative.include
> +		local	user.relative=include
> +		command	user.cmdline=true
> +	EOF

The HERE-DOC is over-indented.  All the body lines should align with
cat and EOF.  The same comment applies to many "<<-" added by this
patch---mimick the "<<-" that appear in earlier part of the same
file.

> +test_expect_success !MINGW '--show-scope with --blob' '
> +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
> +	cat >expect <<-EOF &&
> +		command	user.custom=true
> +	EOF
> +	git config --blob=$blob --show-scope --list >output &&
> +	test_cmp expect output
> +'

Missing blank line between two tests.

I wonder if we want to revamp the tests for --show-origin that wants
to make sure a funny filename is quoted properly.  For that purpose,
CUSTOM_CONFIG_FILE is given a funny pathname, and it would have been
OK to use that only for a single "do we quote properly?" test, but
instead we use that same funnily-named file as the source in many
places where we do not *care* how --show-origin quotes the pathname
at all, and end up having to skip with !MINGW.

It's a bad tradition that started at 45bf3297 ("t1300: fix the new
--show-origin tests on Windows", 2016-03-23), I guess, and is not a
new problem introduced by this patch, but it should stop so that we
can have a better test coverage everywhere.

Other than that, I think that the new feature added by this series
is a sensible one.  Thanks for working on it.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-17 21:21       ` Junio C Hamano
@ 2020-01-17 21:26         ` Bert Wesarg
  2020-01-18 15:42         ` Matt Rogers
  1 sibling, 0 replies; 98+ messages in thread
From: Bert Wesarg @ 2020-01-17 21:26 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Matthew Rogers via GitGitGadget, Git Mailing List, Matthew Rogers

On Fri, Jan 17, 2020 at 10:21 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > +--show-scope::
> > +     Similar to `--show-origin` in that it augments the output of
> > +     all queried config options with the scope of that value
> > +     (local, global, system, command).
> > +
> >  --get-colorbool name [stdout-is-tty]::
> >
> >       Find the color setting for `name` (e.g. `color.diff`) and output
> > diff --git a/builtin/config.c b/builtin/config.c
> > index 52a904cfb1..d5931061e8 100644
> > --- a/builtin/config.c
> > +++ b/builtin/config.c
> > @@ -33,6 +33,7 @@ static int end_nul;
> >  static int respect_includes_opt = -1;
> >  static struct config_options config_options;
> >  static int show_origin;
> > +static int show_scope;
> >
> >  #define ACTION_GET (1<<0)
> >  #define ACTION_GET_ALL (1<<1)
> > @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
> >       OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
> >       OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
> >       OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
> > +     OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
> >       OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
> >       OPT_END(),
> >  };
> > @@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)
> >       strbuf_addch(buf, term);
> >  }
> >
> > +static const char *scope_to_string(enum config_scope scope)
> > +{
> > +     switch (scope) {
> > +     case CONFIG_SCOPE_LOCAL:
> > +             return "local";
> > +     case CONFIG_SCOPE_GLOBAL:
> > +             return "global";
> > +     case CONFIG_SCOPE_SYSTEM:
> > +             return "system";
> > +     case CONFIG_SCOPE_WORKTREE:
> > +             return "worktree";
> > +     case CONFIG_SCOPE_COMMAND:
> > +             return "command";
> > +     case CONFIG_SCOPE_SUBMODULE:
> > +             return "submodule";
> > +     default:
> > +             return "unknown";
> > +     }
> > +}
>
> It is a shame that with this defined in the main part of the system
> test-tool still needs to carry its own private copy.
>
> I wonder if it results in a better system if we rename this to
>
>         const char *config_scope_name(enum config_scope scope)
>
> made it externally visible, and use it in t/helper/test-config.c
> and get rid of the private copy scope_name() there?
>

+1 and please keep the order in config_scope_name the same as in the
enum definition. Will base my 'remote rename &
branch.<name>.pushRemote'  series on this then.

Bert

> > diff --git a/config.h b/config.h
> > index f383a71404..91f851e925 100644
> > --- a/config.h
> > +++ b/config.h
> > @@ -35,10 +35,21 @@ struct object_id;
> >
> >  #define CONFIG_REGEX_NONE ((void *)1)
> >
> > +enum config_scope {
> > +     CONFIG_SCOPE_UNKNOWN = 0,
> > +     CONFIG_SCOPE_SYSTEM,
> > +     CONFIG_SCOPE_GLOBAL,
> > +     CONFIG_SCOPE_LOCAL,
> > +     CONFIG_SCOPE_WORKTREE,
> > +     CONFIG_SCOPE_COMMAND,
> > +     CONFIG_SCOPE_SUBMODULE,
> > +};
> > +
>
> And this is the logical place to make an external definition, if we
> were to go that route.
>
> > diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> > index 983a0a1583..b654a6d2f9 100755
> > --- a/t/t1300-config.sh
> > +++ b/t/t1300-config.sh
> > @@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '
> >       test_cmp expect output
> >  '
> >
> > +test_expect_success '--show-scope with --list' '
> > +     cat >expect <<-EOF &&
> > +             global  user.global=true
> > +             global  user.override=global
> > +             global  include.path=$INCLUDE_DIR/absolute.include
> > +             global  user.absolute=include
> > +             local   user.local=true
> > +             local   user.override=local
> > +             local   include.path=../include/relative.include
> > +             local   user.relative=include
> > +             command user.cmdline=true
> > +     EOF
>
> The HERE-DOC is over-indented.  All the body lines should align with
> cat and EOF.  The same comment applies to many "<<-" added by this
> patch---mimick the "<<-" that appear in earlier part of the same
> file.
>
> > +test_expect_success !MINGW '--show-scope with --blob' '
> > +     blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
> > +     cat >expect <<-EOF &&
> > +             command user.custom=true
> > +     EOF
> > +     git config --blob=$blob --show-scope --list >output &&
> > +     test_cmp expect output
> > +'
>
> Missing blank line between two tests.
>
> I wonder if we want to revamp the tests for --show-origin that wants
> to make sure a funny filename is quoted properly.  For that purpose,
> CUSTOM_CONFIG_FILE is given a funny pathname, and it would have been
> OK to use that only for a single "do we quote properly?" test, but
> instead we use that same funnily-named file as the source in many
> places where we do not *care* how --show-origin quotes the pathname
> at all, and end up having to skip with !MINGW.
>
> It's a bad tradition that started at 45bf3297 ("t1300: fix the new
> --show-origin tests on Windows", 2016-03-23), I guess, and is not a
> new problem introduced by this patch, but it should stop so that we
> can have a better test coverage everywhere.
>
> Other than that, I think that the new feature added by this series
> is a sensible one.  Thanks for working on it.
>

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 2/4] config: refine config scope enum
  2020-01-17 20:44       ` Junio C Hamano
@ 2020-01-18 15:27         ` Matt Rogers
  2020-01-18 18:09           ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Matt Rogers @ 2020-01-18 15:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

> So the gist of the change is to split REPO into two, LOCAL and
> WORKTREE.
>
> If we can find a way to state that concisely, perhaps we can improve
> "refine enum" and make it more informative.
>

Should I just say "split repo scope" Or is that too on the nose?

> > diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> > index 214003d5b2..6695e463eb 100644
> > --- a/t/helper/test-config.c
> > +++ b/t/helper/test-config.c
> > @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
> >               return "system";
> >       case CONFIG_SCOPE_GLOBAL:
> >               return "global";
> > -     case CONFIG_SCOPE_REPO:
> > +     case CONFIG_SCOPE_LOCAL:
> >               return "repo";
> > +     case CONFIG_SCOPE_WORKTREE:
> > +             return "worktree";
> >       case CONFIG_SCOPE_CMDLINE:
> >               return "cmdline";
> >       default:
> > diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> > index 7b4e1a63eb..535b2a73f7 100755
> > --- a/t/t1308-config-set.sh
> > +++ b/t/t1308-config-set.sh
> > @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
> >       value=from-cmdline
> >       origin=command line
> >       name=
> > -     scope=cmdline
> > +     scope=command
>
> Why???

I meant to put this change into the next series in the patch, but I
must have messed up, so I'll readjust that.


-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 3/4] config: clarify meaning of command line scoping
  2020-01-17 21:00       ` Junio C Hamano
@ 2020-01-18 15:33         ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-18 15:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

> we have such a scope for one-shot settings and these three
> sources are already treated as the same class.
>

So this isn't technically correct, as before the final patch of this series we
technically don't set the current_parsing_scope for those options.  This
doesn't actually affect anything though, because before then nothing actually
checks the current_parsing_scope during such calls to git config.  As such,
it makes sense to me to keep that part of the commit message.

> > This patch introduces
> > CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
> > CONFIG_SCOPE_CMDLINE redundant.
>
> The change in this commit is to rename CMDLINE to COMMAND.  That is
> what the proposed log message for this step must justify.
>
>         We internally use CONFIG_SCOPE_CMDLINE for the scope for the
>         configuration variables that come from "git -c VAR=VAL",
>         "git config --file=FILE" and "git config --blob=BLOB".  As
>         we are going to expose the scope names to end-users in the
>         next step, let's rethink the half-cryptic "cmdline" and
>         instead use a proper word "command" (the settings from three
>         sources in this scope are all in effect only during a single
>         invocation of a git command).
>
> or something like that.

I like this explanation much better so I'll roll that into the commit message.
>
>
> > --- a/t/helper/test-config.c
> > +++ b/t/helper/test-config.c
> > @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
> >               return "repo";
> >       case CONFIG_SCOPE_WORKTREE:
> >               return "worktree";
> > -     case CONFIG_SCOPE_CMDLINE:
> > -             return "cmdline";
> > +     case CONFIG_SCOPE_COMMAND:
> > +             return "command";
>
> The only externally observable effect of this patch is this output
> string from test-tool and we are not breaking end-user experience,
> but I am not sure if this churn is worth it.  I dunno.
>
> In any case, the change to t1308 we saw in the previous step belongs
> to this step, I think.

Yeah, this was my bad...



-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value
  2020-01-17 21:21       ` Junio C Hamano
  2020-01-17 21:26         ` Bert Wesarg
@ 2020-01-18 15:42         ` Matt Rogers
  1 sibling, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-18 15:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, git

> The HERE-DOC is over-indented.  All the body lines should align with
> cat and EOF.  The same comment applies to many "<<-" added by this
> patch---mimick the "<<-" that appear in earlier part of the same
> file.
>

I was mimicking the style of the --show-origin tests, and didn't realize this
was a style violation.  This is done in a few tests, so I'll add a patch
that just goes through the file and fixes that for the existing tests as well.


> I wonder if we want to revamp the tests for --show-origin that wants
> to make sure a funny filename is quoted properly.  For that purpose,
> CUSTOM_CONFIG_FILE is given a funny pathname, and it would have been
> OK to use that only for a single "do we quote properly?" test, but
> instead we use that same funnily-named file as the source in many
> places where we do not *care* how --show-origin quotes the pathname
> at all, and end up having to skip with !MINGW.
>
> It's a bad tradition that started at 45bf3297 ("t1300: fix the new
> --show-origin tests on Windows", 2016-03-23), I guess, and is not a
> new problem introduced by this patch, but it should stop so that we
> can have a better test coverage everywhere.
>

Agreed.

> Other than that, I think that the new feature added by this series
> is a sensible one.  Thanks for working on it.
>

You're welcome!  And thank you for the careful review.


-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v3 2/4] config: refine config scope enum
  2020-01-18 15:27         ` Matt Rogers
@ 2020-01-18 18:09           ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-18 18:09 UTC (permalink / raw)
  To: Matt Rogers; +Cc: Matthew Rogers via GitGitGadget, git

Matt Rogers <mattr94@gmail.com> writes:

>> So the gist of the change is to split REPO into two, LOCAL and
>> WORKTREE.
>>
>> If we can find a way to state that concisely, perhaps we can improve
>> "refine enum" and make it more informative.
>>
>
> Should I just say "split repo scope" Or is that too on the nose?

Yeah, I think phrasing along that line would work well.

	config: split repo scope to local and worktree

That's 46 chars.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 0/6] config: allow user to know scope of config options
  2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                       ` (3 preceding siblings ...)
  2020-01-17 15:31     ` [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21     ` Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
                         ` (7 more replies)
  4 siblings, 8 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v3:

 * Cleaned up t1300
 * Expanded test coverage for t1300 to not rely as much on !MINGW by using a
   simpler filename for most tests
 * config_scope_name is now exposed in config.h
 * cleaned up commit messages for clarity/content (again)

Matthew Rogers (6):
  config: fix typo in variable name
  t1300: fix over-indented HERE-DOCs
  t1300: create custom config file without special characters
  config: split repo scope to local and worktree
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt |  15 ++-
 builtin/config.c             |  46 +++++--
 config.c                     |  35 ++++-
 config.h                     |  20 +--
 remote.c                     |   3 +-
 submodule-config.c           |   4 +-
 t/helper/test-config.c       |  17 +--
 t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------
 t/t1308-config-set.sh        |   4 +-
 upload-pack.c                |   3 +-
 10 files changed, 248 insertions(+), 139 deletions(-)


base-commit: 232378479ee6c66206d47a9be175e3a39682aea6
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v3:

 1:  f5a81a4d25 = 1:  f5a81a4d25 config: fix typo in variable name
 -:  ---------- > 2:  1b42f85399 t1300: fix over-indented HERE-DOCs
 -:  ---------- > 3:  9d19794dfd t1300: create custom config file without special characters
 2:  f06f9291b7 ! 4:  9f160e281a config: refine config scope enum
     @@ -1,6 +1,6 @@
      Author: Matthew Rogers <mattr94@gmail.com>
      
     -    config: refine config scope enum
     +    config: split repo scope to local and worktree
      
          Previously when iterating through git config variables, worktree config
          and local config were both considered "CONFIG_SCOPE_REPO".  This was
     @@ -93,14 +93,14 @@
       --- a/t/t1308-config-set.sh
       +++ b/t/t1308-config-set.sh
      @@
     + 	value=from-repo
     + 	origin=file
     + 	name=.git/config
     +-	scope=repo
     ++	scope=local
     + 
     + 	key=foo.bar
       	value=from-cmdline
     - 	origin=command line
     - 	name=
     --	scope=cmdline
     -+	scope=command
     - 	EOF
     - 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
     - 	test_cmp expect actual
      
       diff --git a/upload-pack.c b/upload-pack.c
       --- a/upload-pack.c
 3:  97b8a7641d ! 5:  7f00f8559d config: clarify meaning of command line scoping
     @@ -53,3 +53,16 @@
       	default:
       		return "unknown";
       	}
     +
     + diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
     + --- a/t/t1308-config-set.sh
     + +++ b/t/t1308-config-set.sh
     +@@
     + 	value=from-cmdline
     + 	origin=command line
     + 	name=
     +-	scope=cmdline
     ++	scope=command
     + 	EOF
     + 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
     + 	test_cmp expect actual
 4:  61ff3c64b5 ! 6:  5549db7e39 config: add '--show-scope' to print the scope of a config value
     @@ -76,26 +76,6 @@
       	strbuf_addch(buf, term);
       }
       
     -+static const char *scope_to_string(enum config_scope scope)
     -+{
     -+	switch (scope) {
     -+	case CONFIG_SCOPE_LOCAL:
     -+		return "local";
     -+	case CONFIG_SCOPE_GLOBAL:
     -+		return "global";
     -+	case CONFIG_SCOPE_SYSTEM:
     -+		return "system";
     -+	case CONFIG_SCOPE_WORKTREE:
     -+		return "worktree";
     -+	case CONFIG_SCOPE_COMMAND:
     -+		return "command";
     -+	case CONFIG_SCOPE_SUBMODULE:
     -+		return "submodule";
     -+	default:
     -+		return "unknown";
     -+	}
     -+}
     -+
      +static void show_config_scope(struct strbuf *buf)
      +{
      +	const char term = end_nul ? '\0' : '\t';
     @@ -211,6 +191,33 @@
       	/*
       	 * If we have a specific filename, use it. Otherwise, follow the
       	 * regular lookup sequence.
     +@@
     + 	}
     + }
     + 
     ++const char *scope_to_string(enum config_scope scope)
     ++{
     ++	switch (scope) {
     ++	case CONFIG_SCOPE_SYSTEM:
     ++		return "system";
     ++	case CONFIG_SCOPE_GLOBAL:
     ++		return "global";
     ++	case CONFIG_SCOPE_LOCAL:
     ++		return "local";
     ++	case CONFIG_SCOPE_WORKTREE:
     ++		return "worktree";
     ++	case CONFIG_SCOPE_COMMAND:
     ++		return "command";
     ++	case CONFIG_SCOPE_SUBMODULE:
     ++		return "submodule";
     ++	default:
     ++		return "unknown";
     ++	}
     ++}
     ++
     + const char *current_config_name(void)
     + {
     + 	const char *name;
      
       diff --git a/config.h b/config.h
       --- a/config.h
     @@ -228,6 +235,7 @@
      +	CONFIG_SCOPE_COMMAND,
      +	CONFIG_SCOPE_SUBMODULE,
      +};
     ++const char *scope_to_string(enum config_scope scope);
      +
       struct git_config_source {
       	unsigned int use_stdin:1;
     @@ -273,14 +281,38 @@
       --- a/t/helper/test-config.c
       +++ b/t/helper/test-config.c
      @@
     - 		return "repo";
     - 	case CONFIG_SCOPE_WORKTREE:
     - 		return "worktree";
     -+	case CONFIG_SCOPE_SUBMODULE:
     -+		return "submodule";
     - 	case CONFIG_SCOPE_COMMAND:
     - 		return "command";
     - 	default:
     +  *
     +  */
     + 
     +-static const char *scope_name(enum config_scope scope)
     +-{
     +-	switch (scope) {
     +-	case CONFIG_SCOPE_SYSTEM:
     +-		return "system";
     +-	case CONFIG_SCOPE_GLOBAL:
     +-		return "global";
     +-	case CONFIG_SCOPE_LOCAL:
     +-		return "repo";
     +-	case CONFIG_SCOPE_WORKTREE:
     +-		return "worktree";
     +-	case CONFIG_SCOPE_COMMAND:
     +-		return "command";
     +-	default:
     +-		return "unknown";
     +-	}
     +-}
     + static int iterate_cb(const char *var, const char *value, void *data)
     + {
     + 	static int nr;
     +@@
     + 	printf("value=%s\n", value ? value : "(null)");
     + 	printf("origin=%s\n", current_config_origin_type());
     + 	printf("name=%s\n", current_config_name());
     +-	printf("scope=%s\n", scope_name(current_config_scope()));
     ++	printf("scope=%s\n", scope_to_string(current_config_scope()));
     + 
     + 	return 0;
     + }
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
     @@ -313,6 +345,7 @@
      +	git config --blob=$blob --show-scope --list >output &&
      +	test_cmp expect output
      +'
     ++
      +test_expect_success '--show-scope with --local' '
      +	cat >expect <<-\EOF &&
      +		local	user.local=true

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 1/6] config: fix typo in variable name
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
                         ` (6 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24 18:43         ` Junio C Hamano
  2020-01-24  0:21       ` [PATCH v4 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
                         ` (5 subsequent siblings)
  7 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Prepare for the following patches by removing extraneous indents from
HERE-DOCs used in config tests.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..e8b4575758 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		Qr = value2
+	[V.A]
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.a.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		QR = value2
+	[V.A]
+	QR = value2
 	EOF
 	git config -f testConfig_actual "V.a.R" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "V.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual
@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V "A"]
-		R = v1
-		[K "E"]
-		Y = v1
-		[a "b"]
-		c = v1
-		[d "e"]
-		f = v1
+	[V "A"]
+	R = v1
+	[K "E"]
+	Y = v1
+	[a "b"]
+	c = v1
+	[d "e"]
+	f = v1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V "A"]
-		Qr = v2
-		[K "E"]
-		Qy = v2
-		[a "b"]
-		Qc = v2
-		[d "e"]
-		f = v1
-		[d "E"]
-		Qf = v2
+	[V "A"]
+	Qr = v2
+	[K "E"]
+	Qy = v2
+	[a "b"]
+	Qc = v2
+	[d "e"]
+	f = v1
+	[d "E"]
+	Qf = v2
 	EOF
 	# exact match
 	git config -f testConfig_actual a.b.c v2 &&
@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '
 	INCLUDE_DIR="$HOME/include" &&
 	mkdir -p "$INCLUDE_DIR" &&
 	cat >"$INCLUDE_DIR"/absolute.include <<-\EOF &&
-		[user]
-			absolute = include
+	[user]
+		absolute = include
 	EOF
 	cat >"$INCLUDE_DIR"/relative.include <<-\EOF &&
-		[user]
-			relative = include
+	[user]
+		relative = include
 	EOF
 	cat >"$HOME"/.gitconfig <<-EOF &&
-		[user]
-			global = true
-			override = global
-		[include]
-			path = "$INCLUDE_DIR/absolute.include"
+	[user]
+		global = true
+		override = global
+	[include]
+		path = "$INCLUDE_DIR/absolute.include"
 	EOF
 	cat >.git/config <<-\EOF
-		[user]
-			local = true
-			override = local
-		[include]
-			path = ../include/relative.include
+	[user]
+		local = true
+		override = local
+	[include]
+		path = ../include/relative.include
 	EOF
 '
 
 test_expect_success '--show-origin with --list' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global=true
-		file:$HOME/.gitconfig	user.override=global
-		file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
-		file:$INCLUDE_DIR/absolute.include	user.absolute=include
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
-		file:.git/../include/relative.include	user.relative=include
-		command line:	user.cmdline=true
+	file:$HOME/.gitconfig	user.global=true
+	file:$HOME/.gitconfig	user.override=global
+	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
+	file:.git/../include/relative.include	user.relative=include
+	command line:	user.cmdline=true
 	EOF
 	git -c user.cmdline=true config --list --show-origin >output &&
 	test_cmp expect output
@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '
 
 test_expect_success '--show-origin with --list --null' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfigQuser.global
-		trueQfile:$HOME/.gitconfigQuser.override
-		globalQfile:$HOME/.gitconfigQinclude.path
-		$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
-		includeQfile:.git/configQuser.local
-		trueQfile:.git/configQuser.override
-		localQfile:.git/configQinclude.path
-		../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
-		includeQcommand line:Quser.cmdline
-		trueQ
+	file:$HOME/.gitconfigQuser.global
+	trueQfile:$HOME/.gitconfigQuser.override
+	globalQfile:$HOME/.gitconfigQinclude.path
+	$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
+	includeQfile:.git/configQuser.local
+	trueQfile:.git/configQuser.override
+	localQfile:.git/configQinclude.path
+	../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
+	includeQcommand line:Quser.cmdline
+	trueQ
 	EOF
 	git -c user.cmdline=true config --null --list --show-origin >output.raw &&
 	nul_to_q <output.raw >output &&
@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '
 
 test_expect_success '--show-origin with single file' '
 	cat >expect <<-\EOF &&
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
 	EOF
 	git config --local --list --show-origin >output &&
 	test_cmp expect output
@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '
 
 test_expect_success '--show-origin with --get-regexp' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global true
-		file:.git/config	user.local true
+	file:$HOME/.gitconfig	user.global true
+	file:.git/config	user.local true
 	EOF
 	git config --show-origin --get-regexp "user\.[g|l].*" >output &&
 	test_cmp expect output
@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '
 
 test_expect_success '--show-origin getting a single key' '
 	cat >expect <<-\EOF &&
-		file:.git/config	local
+	file:.git/config	local
 	EOF
 	git config --show-origin user.override >output &&
 	test_cmp expect output
@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '
 test_expect_success 'set up custom config file' '
 	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
-		[user]
-			custom = true
+	[user]
+		custom = true
 	EOF
 '
 
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
-		file:"file\" (dq) and spaces.conf"	user.custom=true
+	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
 	test_cmp expect output
@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '
 
 test_expect_success '--show-origin stdin' '
 	cat >expect <<-\EOF &&
-		standard input:	user.custom=true
+	standard input:	user.custom=true
 	EOF
 	git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
 	test_cmp expect output
@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '
 
 test_expect_success '--show-origin stdin with file include' '
 	cat >"$INCLUDE_DIR"/stdin.include <<-EOF &&
-		[user]
-			stdin = include
+	[user]
+		stdin = include
 	EOF
 	cat >expect <<-EOF &&
-		file:$INCLUDE_DIR/stdin.include	include
+	file:$INCLUDE_DIR/stdin.include	include
 	EOF
 	echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" |
 	git config --show-origin --includes --file - user.stdin >output &&
@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '
 test_expect_success !MINGW '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
-		blob:$blob	user.custom=true
+	blob:$blob	user.custom=true
 	EOF
 	git config --blob=$blob --show-origin --list >output &&
 	test_cmp expect output
@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '
 
 test_expect_success !MINGW '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-		blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 3/6] t1300: create custom config file without special characters
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24 18:45         ` Junio C Hamano
  2020-01-24  0:21       ` [PATCH v4 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
                         ` (4 subsequent siblings)
  7 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Tests that required a custom configuration file to be created previously
used a file with non-alphanumeric characters including escaped double
quotes.  This is not really necessary for the majority of tests
involving custom config files, and decreases test coverage on systems
that dissallow such filenames (Windows, etc.).

Create two files, one appropriate for testing quoting and one
appropriate for general use.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 t/t1300-config.sh | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e8b4575758..e5fb9114f6 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '
 '
 
 test_expect_success 'set up custom config file' '
-	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
+	CUSTOM_CONFIG_FILE="custom.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
 	[user]
 		custom = true
 	EOF
 '
 
+test_expect_success !MINGW 'set up custom config file with special name characters' '
+	WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" &&
+	cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE"
+'
+
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
 	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
-	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
+	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
 	test_cmp expect output
 '
 
@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob' '
+test_expect_success '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
 	blob:$blob	user.custom=true
@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob ref' '
+test_expect_success '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:master:custom.conf	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 4/6] config: split repo scope to local and worktree
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                         ` (2 preceding siblings ...)
  2020-01-24  0:21       ` [PATCH v4 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24 18:49         ` Junio C Hamano
  2020-01-24 19:09         ` Junio C Hamano
  2020-01-24  0:21       ` [PATCH v4 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                         ` (3 subsequent siblings)
  7 siblings, 2 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases, but future functionality may care whether or not the config
options come from a worktree or from the repository's actual local
config file.  For example, the planned feature to add a '--show-scope'
to config to allow a user to see which scope listed config options come
from would confuse users if it just printed 'repo' rather than 'local'
or 'worktree' as the documentation would lead them to expect.  As well
as the additional benefit of making the implementation look more like
how the documentation describes the interface.

To accomplish this we split out what was previously considered repo
scope to be local and worktree.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 4 +++-
 t/t1308-config-set.sh  | 2 +-
 upload-pack.c          | 3 ++-
 6 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..6695e463eb 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
+	case CONFIG_SCOPE_LOCAL:
 		return "repo";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7b4e1a63eb..90196e2862 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-repo
 	origin=file
 	name=.git/config
-	scope=repo
+	scope=local
 
 	key=foo.bar
 	value=from-cmdline
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 5/6] config: clarify meaning of command line scoping
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                         ` (3 preceding siblings ...)
  2020-01-24  0:21       ` [PATCH v4 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24  0:21       ` [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
                         ` (2 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  Options passed in using this
mechanism share similar scoping characteristics with the --file and
--blob options of the 'config' command, namely that they are only in use
for that single invocation of git, and that they supersede the normal
system/global/local hierarchy.  This patch introduces
CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
CONFIG_SCOPE_CMDLINE redundant.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 t/t1308-config-set.sh  | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 6695e463eb..78bbb9eb98 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 90196e2862..fba0abe429 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=cmdline
+	scope=command
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                         ` (4 preceding siblings ...)
  2020-01-24  0:21       ` [PATCH v4 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-24  0:21       ` Matthew Rogers via GitGitGadget
  2020-01-24 19:18         ` Junio C Hamano
  2020-01-24 20:22         ` Junio C Hamano
  2020-01-24 19:22       ` [PATCH v4 0/6] config: allow user to know scope of config options Junio C Hamano
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
  7 siblings, 2 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++---
 builtin/config.c             | 36 +++++++++++++++++++---
 config.c                     | 26 +++++++++++++++-
 config.h                     | 21 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       | 19 +-----------
 t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
 7 files changed, 141 insertions(+), 39 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..2e47765aab 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value 
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..66d2b0d2df 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +227,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..469dff57b4 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)
 	}
 }
 
+const char *scope_to_string(enum config_scope scope)
+{
+	switch (scope) {
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
 const char *current_config_name(void)
 {
 	const char *name;
diff --git a/config.h b/config.h
index f383a71404..7b3aec0092 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,22 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+const char *scope_to_string(enum config_scope scope);
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 78bbb9eb98..2e91879b2a 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -37,23 +37,6 @@
  *
  */
 
-static const char *scope_name(enum config_scope scope)
-{
-	switch (scope) {
-	case CONFIG_SCOPE_SYSTEM:
-		return "system";
-	case CONFIG_SCOPE_GLOBAL:
-		return "global";
-	case CONFIG_SCOPE_LOCAL:
-		return "repo";
-	case CONFIG_SCOPE_WORKTREE:
-		return "worktree";
-	case CONFIG_SCOPE_COMMAND:
-		return "command";
-	default:
-		return "unknown";
-	}
-}
 static int iterate_cb(const char *var, const char *value, void *data)
 {
 	static int nr;
@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
 	printf("value=%s\n", value ? value : "(null)");
 	printf("origin=%s\n", current_config_origin_type());
 	printf("name=%s\n", current_config_name());
-	printf("scope=%s\n", scope_name(current_config_scope()));
+	printf("scope=%s\n", scope_to_string(current_config_scope()));
 
 	return 0;
 }
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e5fb9114f6..79dbea9bd1 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		global	user.global=true
+		global	user.override=global
+		global	include.path=$INCLUDE_DIR/absolute.include
+		global	user.absolute=include
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+		local	user.relative=include
+		command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope getting a single value' '
+	cat >expect <<-\EOF &&
+		local	true
+	EOF
+	git config --show-scope --get user.local >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		global	file:$HOME/.gitconfig	user.global=true
+		global	file:$HOME/.gitconfig	user.override=global
+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		local	file:.git/config	user.local=true
+		local	file:.git/config	user.override=local
+		local	file:.git/config	include.path=../include/relative.include
+		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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs
  2020-01-24  0:21       ` [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
@ 2020-01-24 18:43         ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 18:43 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Prepare for the following patches by removing extraneous indents from
> HERE-DOCs used in config tests.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------
>  1 file changed, 84 insertions(+), 84 deletions(-)

This step is new.  It makes sense, I think.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 3/6] t1300: create custom config file without special characters
  2020-01-24  0:21       ` [PATCH v4 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
@ 2020-01-24 18:45         ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 18:45 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Tests that required a custom configuration file to be created previously
> used a file with non-alphanumeric characters including escaped double
> quotes.  This is not really necessary for the majority of tests
> involving custom config files, and decreases test coverage on systems
> that dissallow such filenames (Windows, etc.).
>
> Create two files, one appropriate for testing quoting and one
> appropriate for general use.

Nicely done.

>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  t/t1300-config.sh | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> index e8b4575758..e5fb9114f6 100755
> --- a/t/t1300-config.sh
> +++ b/t/t1300-config.sh
> @@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '
>  '
>  
>  test_expect_success 'set up custom config file' '
> -	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
> +	CUSTOM_CONFIG_FILE="custom.conf" &&
>  	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
>  	[user]
>  		custom = true
>  	EOF
>  '
>  
> +test_expect_success !MINGW 'set up custom config file with special name characters' '
> +	WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" &&
> +	cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE"
> +'

OK.

>  test_expect_success !MINGW '--show-origin escape special file name characters' '
>  	cat >expect <<-\EOF &&
>  	file:"file\" (dq) and spaces.conf"	user.custom=true
>  	EOF
> -	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
> +	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
>  	test_cmp expect output
>  '
>  
> @@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '
>  	test_cmp expect output
>  '
>  
> -test_expect_success !MINGW '--show-origin blob' '
> +test_expect_success '--show-origin blob' '
>  	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
>  	cat >expect <<-EOF &&
>  	blob:$blob	user.custom=true
> @@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '
>  	test_cmp expect output
>  '
>  
> -test_expect_success !MINGW '--show-origin blob ref' '
> +test_expect_success '--show-origin blob ref' '
>  	cat >expect <<-\EOF &&
> -	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
> +	blob:master:custom.conf	user.custom=true
>  	EOF
>  	git add "$CUSTOM_CONFIG_FILE" &&
>  	git commit -m "new config file" &&

Nice to see these cleaned up.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 4/6] config: split repo scope to local and worktree
  2020-01-24  0:21       ` [PATCH v4 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-01-24 18:49         ` Junio C Hamano
  2020-01-24 19:09         ` Junio C Hamano
  1 sibling, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 18:49 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Previously when iterating through git config variables, worktree config
> and local config were both considered "CONFIG_SCOPE_REPO".  This was
> never a problem before as no one had needed to differentiate between the
> two cases, but future functionality may care whether or not the config
> options come from a worktree or from the repository's actual local
> config file.  For example, the planned feature to add a '--show-scope'
> to config to allow a user to see which scope listed config options come
> from would confuse users if it just printed 'repo' rather than 'local'
> or 'worktree' as the documentation would lead them to expect.  As well
> as the additional benefit of making the implementation look more like
> how the documentation describes the interface.
>
> To accomplish this we split out what was previously considered repo
> scope to be local and worktree.
>
> The clients of 'current_config_scope()' who cared about
> CONFIG_SCOPE_REPO are also modified to similarly care about
> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  config.c               | 7 ++-----
>  config.h               | 3 ++-
>  remote.c               | 3 ++-
>  t/helper/test-config.c | 4 +++-
>  t/t1308-config-set.sh  | 2 +-
>  upload-pack.c          | 3 ++-
>  6 files changed, 12 insertions(+), 10 deletions(-)

Nicely done.

> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 7b4e1a63eb..90196e2862 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-repo
>  	origin=file
>  	name=.git/config
> -	scope=repo
> +	scope=local
>  
>  	key=foo.bar
>  	value=from-cmdline

OK.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 4/6] config: split repo scope to local and worktree
  2020-01-24  0:21       ` [PATCH v4 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
  2020-01-24 18:49         ` Junio C Hamano
@ 2020-01-24 19:09         ` Junio C Hamano
  1 sibling, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 19:09 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 214003d5b2..6695e463eb 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
>  		return "system";
>  	case CONFIG_SCOPE_GLOBAL:
>  		return "global";
> -	case CONFIG_SCOPE_REPO:
> +	case CONFIG_SCOPE_LOCAL:
>  		return "repo";

This must be updated to "local", no, to match the change to t1308?

> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
>  	case CONFIG_SCOPE_CMDLINE:
>  		return "cmdline";
>  	default:
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 7b4e1a63eb..90196e2862 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-repo
>  	origin=file
>  	name=.git/config
> -	scope=repo
> +	scope=local


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-24  0:21       ` [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-24 19:18         ` Junio C Hamano
  2020-01-24 20:22         ` Junio C Hamano
  1 sibling, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 19:18 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +const char *scope_to_string(enum config_scope scope)
> +{
> +	switch (scope) {
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";

Despite the screw-up at an earlier step, this one is correct ;-)

> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
> +	default:
> +		return "unknown";
> +	}
> +}
> +

> diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> index e5fb9114f6..79dbea9bd1 100755
> --- a/t/t1300-config.sh
> +++ b/t/t1300-config.sh
> @@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
>  	test_cmp expect output
>  '
>  
> +test_expect_success '--show-scope with --list' '
> +	cat >expect <<-EOF &&
> +		global	user.global=true
> +		global	user.override=global
> +		global	include.path=$INCLUDE_DIR/absolute.include
> +		global	user.absolute=include
> +		local	user.local=true
> +		local	user.override=local
> +		local	include.path=../include/relative.include
> +		local	user.relative=include
> +		command	user.cmdline=true
> +	EOF

We cleaned up the existing ones that are overly indented from this
script in an earlier step.  Let's not re-introduce them.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 0/6] config: allow user to know scope of config options
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                         ` (5 preceding siblings ...)
  2020-01-24  0:21       ` [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-24 19:22       ` Junio C Hamano
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
  7 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 19:22 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> This was originally a pull request to the git-for-windows repository
> [https://github.com/git-for-windows/git/pull/2399]. It adds a new option
> --show-scope which would allow a user to see what scope a given
> configuration value has (sytem, local, global, etc.).

These generally look very good.

I'll queue them with proposed fix-ups, so please do not waste your
time by reworking on your patches in response to my review comments
before fetching today's integration result from the public
repository, which probably will happen in 5 hours or so.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-24  0:21       ` [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  2020-01-24 19:18         ` Junio C Hamano
@ 2020-01-24 20:22         ` Junio C Hamano
  2020-01-24 20:49           ` Matt Rogers
  1 sibling, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-24 20:22 UTC (permalink / raw)
  To: Matthew Rogers; +Cc: git, Bert Wesarg, Matthew Rogers via GitGitGadget

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +const char *scope_to_string(enum config_scope scope)
> +{
> +	switch (scope) {
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
> +	default:
> +		return "unknown";
> +	}
> +}

In earlier round(s), this was called config_scope_name(), wasn't it?

"scope_to_string()" is a much worse than "config_scope_name()" as a
name of a global function (e.g. we won't know what subsystems other
than "config" may want to use "scope").  As you remember, Bert's
"remote rename" series wants to use a public interface like this
function, and the series expects this function to be called
config_scope_name().  Let's not rename a public API function
suddenly---it disrupts other topics in flight.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-24 20:22         ` Junio C Hamano
@ 2020-01-24 20:49           ` Matt Rogers
  2020-01-25  0:10             ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Matt Rogers @ 2020-01-24 20:49 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git Mailing List, Bert Wesarg, Matthew Rogers via GitGitGadget

I think this was a mess-up on my end.  I had meant to rename it to
config_scope_name() (after talking with Bert) but it appears that I
had messed up, so I think my mistake wasn't to rename the function, but
to fail to rename it.  So I do apologize.

On Fri, Jan 24, 2020 at 3:22 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > +const char *scope_to_string(enum config_scope scope)
> > +{
> > +     switch (scope) {
> > +     case CONFIG_SCOPE_SYSTEM:
> > +             return "system";
> > +     case CONFIG_SCOPE_GLOBAL:
> > +             return "global";
> > +     case CONFIG_SCOPE_LOCAL:
> > +             return "local";
> > +     case CONFIG_SCOPE_WORKTREE:
> > +             return "worktree";
> > +     case CONFIG_SCOPE_COMMAND:
> > +             return "command";
> > +     case CONFIG_SCOPE_SUBMODULE:
> > +             return "submodule";
> > +     default:
> > +             return "unknown";
> > +     }
> > +}
>
> In earlier round(s), this was called config_scope_name(), wasn't it?
>
> "scope_to_string()" is a much worse than "config_scope_name()" as a
> name of a global function (e.g. we won't know what subsystems other
> than "config" may want to use "scope").  As you remember, Bert's
> "remote rename" series wants to use a public interface like this
> function, and the series expects this function to be called
> config_scope_name().  Let's not rename a public API function
> suddenly---it disrupts other topics in flight.
>
> Thanks.



-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-24 20:49           ` Matt Rogers
@ 2020-01-25  0:10             ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-25  0:10 UTC (permalink / raw)
  To: Matt Rogers
  Cc: Git Mailing List, Bert Wesarg, Matthew Rogers via GitGitGadget

Matt Rogers <mattr94@gmail.com> writes:

> I think this was a mess-up on my end.  I had meant to rename it to
> config_scope_name() (after talking with Bert) but it appears that I
> had messed up, so I think my mistake wasn't to rename the function, but
> to fail to rename it.  So I do apologize.

No need to.  I just wanted to make sure everybody involved is aware
of what others are doing to avoid wasted effort.

Now I do expect the (hopefully) final reroll of your topic, so that
Bert can fork his topic on top of it.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 0/6] config: allow user to know scope of config options
  2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                         ` (6 preceding siblings ...)
  2020-01-24 19:22       ` [PATCH v4 0/6] config: allow user to know scope of config options Junio C Hamano
@ 2020-01-25  0:39       ` " Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
                           ` (6 more replies)
  7 siblings, 7 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v3:

 * Cleaned up t1300
 * Expanded test coverage for t1300 to not rely as much on !MINGW by using a
   simpler filename for most tests
 * config_scope_name is now exposed in config.h
 * cleaned up commit messages for clarity/content (again)

Matthew Rogers (6):
  config: fix typo in variable name
  t1300: fix over-indented HERE-DOCs
  t1300: create custom config file without special characters
  config: split repo scope to local and worktree
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt |  15 ++-
 builtin/config.c             |  46 +++++--
 config.c                     |  35 ++++-
 config.h                     |  20 +--
 remote.c                     |   3 +-
 submodule-config.c           |   4 +-
 t/helper/test-config.c       |  17 +--
 t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------
 t/t1308-config-set.sh        |   4 +-
 upload-pack.c                |   3 +-
 10 files changed, 248 insertions(+), 139 deletions(-)


base-commit: 232378479ee6c66206d47a9be175e3a39682aea6
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v4:

 1:  f5a81a4d25 = 1:  f5a81a4d25 config: fix typo in variable name
 2:  1b42f85399 = 2:  1b42f85399 t1300: fix over-indented HERE-DOCs
 3:  9d19794dfd = 3:  9d19794dfd t1300: create custom config file without special characters
 4:  9f160e281a = 4:  9f160e281a config: split repo scope to local and worktree
 5:  7f00f8559d = 5:  7f00f8559d config: clarify meaning of command line scoping
 6:  5549db7e39 = 6:  2e979d9fa5 config: add '--show-scope' to print the scope of a config value

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 1/6] config: fix typo in variable name
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
                           ` (5 subsequent siblings)
  6 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 2/6] t1300: fix over-indented HERE-DOCs
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
                           ` (4 subsequent siblings)
  6 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Prepare for the following patches by removing extraneous indents from
HERE-DOCs used in config tests.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..e8b4575758 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		Qr = value2
+	[V.A]
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.a.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		QR = value2
+	[V.A]
+	QR = value2
 	EOF
 	git config -f testConfig_actual "V.a.R" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "V.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual
@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V "A"]
-		R = v1
-		[K "E"]
-		Y = v1
-		[a "b"]
-		c = v1
-		[d "e"]
-		f = v1
+	[V "A"]
+	R = v1
+	[K "E"]
+	Y = v1
+	[a "b"]
+	c = v1
+	[d "e"]
+	f = v1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V "A"]
-		Qr = v2
-		[K "E"]
-		Qy = v2
-		[a "b"]
-		Qc = v2
-		[d "e"]
-		f = v1
-		[d "E"]
-		Qf = v2
+	[V "A"]
+	Qr = v2
+	[K "E"]
+	Qy = v2
+	[a "b"]
+	Qc = v2
+	[d "e"]
+	f = v1
+	[d "E"]
+	Qf = v2
 	EOF
 	# exact match
 	git config -f testConfig_actual a.b.c v2 &&
@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '
 	INCLUDE_DIR="$HOME/include" &&
 	mkdir -p "$INCLUDE_DIR" &&
 	cat >"$INCLUDE_DIR"/absolute.include <<-\EOF &&
-		[user]
-			absolute = include
+	[user]
+		absolute = include
 	EOF
 	cat >"$INCLUDE_DIR"/relative.include <<-\EOF &&
-		[user]
-			relative = include
+	[user]
+		relative = include
 	EOF
 	cat >"$HOME"/.gitconfig <<-EOF &&
-		[user]
-			global = true
-			override = global
-		[include]
-			path = "$INCLUDE_DIR/absolute.include"
+	[user]
+		global = true
+		override = global
+	[include]
+		path = "$INCLUDE_DIR/absolute.include"
 	EOF
 	cat >.git/config <<-\EOF
-		[user]
-			local = true
-			override = local
-		[include]
-			path = ../include/relative.include
+	[user]
+		local = true
+		override = local
+	[include]
+		path = ../include/relative.include
 	EOF
 '
 
 test_expect_success '--show-origin with --list' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global=true
-		file:$HOME/.gitconfig	user.override=global
-		file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
-		file:$INCLUDE_DIR/absolute.include	user.absolute=include
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
-		file:.git/../include/relative.include	user.relative=include
-		command line:	user.cmdline=true
+	file:$HOME/.gitconfig	user.global=true
+	file:$HOME/.gitconfig	user.override=global
+	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
+	file:.git/../include/relative.include	user.relative=include
+	command line:	user.cmdline=true
 	EOF
 	git -c user.cmdline=true config --list --show-origin >output &&
 	test_cmp expect output
@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '
 
 test_expect_success '--show-origin with --list --null' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfigQuser.global
-		trueQfile:$HOME/.gitconfigQuser.override
-		globalQfile:$HOME/.gitconfigQinclude.path
-		$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
-		includeQfile:.git/configQuser.local
-		trueQfile:.git/configQuser.override
-		localQfile:.git/configQinclude.path
-		../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
-		includeQcommand line:Quser.cmdline
-		trueQ
+	file:$HOME/.gitconfigQuser.global
+	trueQfile:$HOME/.gitconfigQuser.override
+	globalQfile:$HOME/.gitconfigQinclude.path
+	$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
+	includeQfile:.git/configQuser.local
+	trueQfile:.git/configQuser.override
+	localQfile:.git/configQinclude.path
+	../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
+	includeQcommand line:Quser.cmdline
+	trueQ
 	EOF
 	git -c user.cmdline=true config --null --list --show-origin >output.raw &&
 	nul_to_q <output.raw >output &&
@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '
 
 test_expect_success '--show-origin with single file' '
 	cat >expect <<-\EOF &&
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
 	EOF
 	git config --local --list --show-origin >output &&
 	test_cmp expect output
@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '
 
 test_expect_success '--show-origin with --get-regexp' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global true
-		file:.git/config	user.local true
+	file:$HOME/.gitconfig	user.global true
+	file:.git/config	user.local true
 	EOF
 	git config --show-origin --get-regexp "user\.[g|l].*" >output &&
 	test_cmp expect output
@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '
 
 test_expect_success '--show-origin getting a single key' '
 	cat >expect <<-\EOF &&
-		file:.git/config	local
+	file:.git/config	local
 	EOF
 	git config --show-origin user.override >output &&
 	test_cmp expect output
@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '
 test_expect_success 'set up custom config file' '
 	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
-		[user]
-			custom = true
+	[user]
+		custom = true
 	EOF
 '
 
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
-		file:"file\" (dq) and spaces.conf"	user.custom=true
+	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
 	test_cmp expect output
@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '
 
 test_expect_success '--show-origin stdin' '
 	cat >expect <<-\EOF &&
-		standard input:	user.custom=true
+	standard input:	user.custom=true
 	EOF
 	git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
 	test_cmp expect output
@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '
 
 test_expect_success '--show-origin stdin with file include' '
 	cat >"$INCLUDE_DIR"/stdin.include <<-EOF &&
-		[user]
-			stdin = include
+	[user]
+		stdin = include
 	EOF
 	cat >expect <<-EOF &&
-		file:$INCLUDE_DIR/stdin.include	include
+	file:$INCLUDE_DIR/stdin.include	include
 	EOF
 	echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" |
 	git config --show-origin --includes --file - user.stdin >output &&
@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '
 test_expect_success !MINGW '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
-		blob:$blob	user.custom=true
+	blob:$blob	user.custom=true
 	EOF
 	git config --blob=$blob --show-origin --list >output &&
 	test_cmp expect output
@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '
 
 test_expect_success !MINGW '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-		blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 3/6] t1300: create custom config file without special characters
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
                           ` (3 subsequent siblings)
  6 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Tests that required a custom configuration file to be created previously
used a file with non-alphanumeric characters including escaped double
quotes.  This is not really necessary for the majority of tests
involving custom config files, and decreases test coverage on systems
that dissallow such filenames (Windows, etc.).

Create two files, one appropriate for testing quoting and one
appropriate for general use.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 t/t1300-config.sh | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e8b4575758..e5fb9114f6 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '
 '
 
 test_expect_success 'set up custom config file' '
-	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
+	CUSTOM_CONFIG_FILE="custom.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
 	[user]
 		custom = true
 	EOF
 '
 
+test_expect_success !MINGW 'set up custom config file with special name characters' '
+	WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" &&
+	cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE"
+'
+
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
 	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
-	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
+	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
 	test_cmp expect output
 '
 
@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob' '
+test_expect_success '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
 	blob:$blob	user.custom=true
@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob ref' '
+test_expect_success '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:master:custom.conf	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 4/6] config: split repo scope to local and worktree
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
                           ` (2 preceding siblings ...)
  2020-01-25  0:39         ` [PATCH v5 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-27 23:09           ` Junio C Hamano
  2020-01-25  0:39         ` [PATCH v5 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                           ` (2 subsequent siblings)
  6 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases, but future functionality may care whether or not the config
options come from a worktree or from the repository's actual local
config file.  For example, the planned feature to add a '--show-scope'
to config to allow a user to see which scope listed config options come
from would confuse users if it just printed 'repo' rather than 'local'
or 'worktree' as the documentation would lead them to expect.  As well
as the additional benefit of making the implementation look more like
how the documentation describes the interface.

To accomplish this we split out what was previously considered repo
scope to be local and worktree.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 4 +++-
 t/t1308-config-set.sh  | 2 +-
 upload-pack.c          | 3 ++-
 6 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..6695e463eb 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
+	case CONFIG_SCOPE_LOCAL:
 		return "repo";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7b4e1a63eb..90196e2862 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-repo
 	origin=file
 	name=.git/config
-	scope=repo
+	scope=local
 
 	key=foo.bar
 	value=from-cmdline
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 5/6] config: clarify meaning of command line scoping
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
                           ` (3 preceding siblings ...)
  2020-01-25  0:39         ` [PATCH v5 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-25  0:39         ` [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  6 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  Options passed in using this
mechanism share similar scoping characteristics with the --file and
--blob options of the 'config' command, namely that they are only in use
for that single invocation of git, and that they supersede the normal
system/global/local hierarchy.  This patch introduces
CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
CONFIG_SCOPE_CMDLINE redundant.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 t/t1308-config-set.sh  | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 6695e463eb..78bbb9eb98 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 90196e2862..fba0abe429 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=cmdline
+	scope=command
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
                           ` (4 preceding siblings ...)
  2020-01-25  0:39         ` [PATCH v5 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-25  0:39         ` Matthew Rogers via GitGitGadget
  2020-01-27 23:12           ` Junio C Hamano
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  6 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-25  0:39 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++---
 builtin/config.c             | 36 +++++++++++++++++++---
 config.c                     | 26 +++++++++++++++-
 config.h                     | 21 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       | 19 +-----------
 t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
 7 files changed, 141 insertions(+), 39 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..2e47765aab 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value 
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..66d2b0d2df 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +227,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..469dff57b4 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)
 	}
 }
 
+const char *scope_to_string(enum config_scope scope)
+{
+	switch (scope) {
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
 const char *current_config_name(void)
 {
 	const char *name;
diff --git a/config.h b/config.h
index f383a71404..7b3aec0092 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,22 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+const char *scope_to_string(enum config_scope scope);
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 78bbb9eb98..2e91879b2a 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -37,23 +37,6 @@
  *
  */
 
-static const char *scope_name(enum config_scope scope)
-{
-	switch (scope) {
-	case CONFIG_SCOPE_SYSTEM:
-		return "system";
-	case CONFIG_SCOPE_GLOBAL:
-		return "global";
-	case CONFIG_SCOPE_LOCAL:
-		return "repo";
-	case CONFIG_SCOPE_WORKTREE:
-		return "worktree";
-	case CONFIG_SCOPE_COMMAND:
-		return "command";
-	default:
-		return "unknown";
-	}
-}
 static int iterate_cb(const char *var, const char *value, void *data)
 {
 	static int nr;
@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
 	printf("value=%s\n", value ? value : "(null)");
 	printf("origin=%s\n", current_config_origin_type());
 	printf("name=%s\n", current_config_name());
-	printf("scope=%s\n", scope_name(current_config_scope()));
+	printf("scope=%s\n", scope_to_string(current_config_scope()));
 
 	return 0;
 }
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e5fb9114f6..79dbea9bd1 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		global	user.global=true
+		global	user.override=global
+		global	include.path=$INCLUDE_DIR/absolute.include
+		global	user.absolute=include
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+		local	user.relative=include
+		command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope getting a single value' '
+	cat >expect <<-\EOF &&
+		local	true
+	EOF
+	git config --show-scope --get user.local >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		global	file:$HOME/.gitconfig	user.global=true
+		global	file:$HOME/.gitconfig	user.override=global
+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		local	file:.git/config	user.local=true
+		local	file:.git/config	user.override=local
+		local	file:.git/config	include.path=../include/relative.include
+		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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v5 4/6] config: split repo scope to local and worktree
  2020-01-25  0:39         ` [PATCH v5 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-01-27 23:09           ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-27 23:09 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 214003d5b2..6695e463eb 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
>  		return "system";
>  	case CONFIG_SCOPE_GLOBAL:
>  		return "global";
> -	case CONFIG_SCOPE_REPO:
> +	case CONFIG_SCOPE_LOCAL:
>  		return "repo";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";

It used to be only "repo"; now we give either "repo" or "worktree".

>  	case CONFIG_SCOPE_CMDLINE:
>  		return "cmdline";
>  	default:
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 7b4e1a63eb..90196e2862 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-repo
>  	origin=file
>  	name=.git/config
> -	scope=repo
> +	scope=local

But the test expects "local".

This patch cannot be correct.  I recall fixing this manually when I
queued the previous round to 'pu'.  Please double check.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-25  0:39         ` [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-27 23:12           ` Junio C Hamano
  2020-01-28  1:31             ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-01-27 23:12 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> When a user queries config values with --show-origin, often it's
> difficult to determine what the actual "scope" (local, global, etc.) of
> a given value is based on just the origin file.
>
> Teach 'git config' the '--show-scope' option to print the scope of all
> displayed config values.  Note that we should never see anything of
> "submodule" scope as that is only ever used by submodule-config.c when
> parsing the '.gitmodules' file.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  Documentation/git-config.txt | 15 ++++++---
>  builtin/config.c             | 36 +++++++++++++++++++---
>  config.c                     | 26 +++++++++++++++-
>  config.h                     | 21 +++++++------
>  submodule-config.c           |  4 ++-
>  t/helper/test-config.c       | 19 +-----------
>  t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
>  7 files changed, 141 insertions(+), 39 deletions(-)
>
> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
> index 899e92a1c9..2e47765aab 100644
> --- a/Documentation/git-config.txt
> +++ b/Documentation/git-config.txt
> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options
>  SYNOPSIS
>  --------
>  [verse]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
>  'git config' [<file-option>] [--type=<type>] --add name value
>  'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
>  'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
>  'git config' [<file-option>] --unset name [value_regex]
>  'git config' [<file-option>] --unset-all name [value_regex]
>  'git config' [<file-option>] --rename-section old_name new_name
>  'git config' [<file-option>] --remove-section name
> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
> +'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
> @@ -222,6 +222,11 @@ Valid `<type>`'s include:
>  	the actual origin (config file path, ref, or blob id if
>  	applicable).
>  
> +--show-scope::
> +	Similar to `--show-origin` in that it augments the output of
> +	all queried config options with the scope of that value 

There is a trailing SP on this line.  I think I fixed it up when I
queued the last round on 'pu'.  Please double check.

> +	const char *scope = scope_to_string(current_config_scope());

???  Are we using scope_to_string() back again?

I thought I queued a fix-up patch when I queued the last round on
'pu' to unblock the other topic that wanted to build on top.  Please
double check.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-27 23:12           ` Junio C Hamano
@ 2020-01-28  1:31             ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-01-28  1:31 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, Git Mailing List

>
> There is a trailing SP on this line.  I think I fixed it up when I
> queued the last round on 'pu'.  Please double check.
>
> > +     const char *scope = scope_to_string(current_config_scope());
>
> ???  Are we using scope_to_string() back again?
>
> I thought I queued a fix-up patch when I queued the last round on
> 'pu' to unblock the other topic that wanted to build on top.  Please
> double check.
>
> Thanks.

I think I messed up when I pulled those changes...

I can get it all sorted out tomorrow after work

-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 0/6] config: allow user to know scope of config options
  2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
                           ` (5 preceding siblings ...)
  2020-01-25  0:39         ` [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34         ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
                             ` (7 more replies)
  6 siblings, 8 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v4:

 * final cleanups

Matthew Rogers (6):
  config: fix typo in variable name
  t1300: fix over-indented HERE-DOCs
  t1300: create custom config file without special characters
  config: split repo scope to local and worktree
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt |  15 ++-
 builtin/config.c             |  46 +++++--
 config.c                     |  35 ++++-
 config.h                     |  20 +--
 remote.c                     |   3 +-
 submodule-config.c           |   4 +-
 t/helper/test-config.c       |  17 +--
 t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------
 t/t1308-config-set.sh        |   4 +-
 upload-pack.c                |   3 +-
 10 files changed, 248 insertions(+), 139 deletions(-)


base-commit: c7a62075917b3340f908093f63f1161c44ed1475
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v6
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v5:

 1:  f5a81a4d25 ! 1:  18f92f70cf config: fix typo in variable name
     @@ -8,6 +8,7 @@
          malapropism is being fixed.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/builtin/config.c b/builtin/config.c
       --- a/builtin/config.c
 2:  1b42f85399 ! 2:  dc7b3f3b96 t1300: fix over-indented HERE-DOCs
     @@ -6,6 +6,7 @@
          HERE-DOCs used in config tests.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
 3:  9d19794dfd ! 3:  975e652368 t1300: create custom config file without special characters
     @@ -12,6 +12,7 @@
          appropriate for general use.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
 4:  9f160e281a ! 4:  1e406ba430 config: split repo scope to local and worktree
     @@ -22,6 +22,7 @@
          CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/config.c b/config.c
       --- a/config.c
     @@ -81,8 +82,9 @@
       	case CONFIG_SCOPE_GLOBAL:
       		return "global";
      -	case CONFIG_SCOPE_REPO:
     +-		return "repo";
      +	case CONFIG_SCOPE_LOCAL:
     - 		return "repo";
     ++		return "local";
      +	case CONFIG_SCOPE_WORKTREE:
      +		return "worktree";
       	case CONFIG_SCOPE_CMDLINE:
 5:  7f00f8559d ! 5:  936ce91c62 config: clarify meaning of command line scoping
     @@ -12,6 +12,7 @@
          CONFIG_SCOPE_CMDLINE redundant.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/config.c b/config.c
       --- a/config.c
     @@ -43,7 +44,7 @@
       --- a/t/helper/test-config.c
       +++ b/t/helper/test-config.c
      @@
     - 		return "repo";
     + 		return "local";
       	case CONFIG_SCOPE_WORKTREE:
       		return "worktree";
      -	case CONFIG_SCOPE_CMDLINE:
 6:  2e979d9fa5 ! 6:  fc141e8689 config: add '--show-scope' to print the scope of a config value
     @@ -12,6 +12,7 @@
          parsing the '.gitmodules' file.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
       --- a/Documentation/git-config.txt
     @@ -46,7 +47,7 @@
       
      +--show-scope::
      +	Similar to `--show-origin` in that it augments the output of
     -+	all queried config options with the scope of that value 
     ++	all queried config options with the scope of that value
      +	(local, global, system, command).
      +
       --get-colorbool name [stdout-is-tty]::
     @@ -79,7 +80,7 @@
      +static void show_config_scope(struct strbuf *buf)
      +{
      +	const char term = end_nul ? '\0' : '\t';
     -+	const char *scope = scope_to_string(current_config_scope());
     ++	const char *scope = config_scope_name(current_config_scope());
      +
      +	strbuf_addstr(buf, N_(scope));
      +	strbuf_addch(buf, term);
     @@ -195,7 +196,7 @@
       	}
       }
       
     -+const char *scope_to_string(enum config_scope scope)
     ++const char *config_scope_name(enum config_scope scope)
      +{
      +	switch (scope) {
      +	case CONFIG_SCOPE_SYSTEM:
     @@ -235,7 +236,7 @@
      +	CONFIG_SCOPE_COMMAND,
      +	CONFIG_SCOPE_SUBMODULE,
      +};
     -+const char *scope_to_string(enum config_scope scope);
     ++const char *config_scope_name(enum config_scope scope);
      +
       struct git_config_source {
       	unsigned int use_stdin:1;
     @@ -292,7 +293,7 @@
      -	case CONFIG_SCOPE_GLOBAL:
      -		return "global";
      -	case CONFIG_SCOPE_LOCAL:
     --		return "repo";
     +-		return "local";
      -	case CONFIG_SCOPE_WORKTREE:
      -		return "worktree";
      -	case CONFIG_SCOPE_COMMAND:
     @@ -309,7 +310,7 @@
       	printf("origin=%s\n", current_config_origin_type());
       	printf("name=%s\n", current_config_name());
      -	printf("scope=%s\n", scope_name(current_config_scope()));
     -+	printf("scope=%s\n", scope_to_string(current_config_scope()));
     ++	printf("scope=%s\n", config_scope_name(current_config_scope()));
       
       	return 0;
       }
     @@ -323,15 +324,15 @@
       
      +test_expect_success '--show-scope with --list' '
      +	cat >expect <<-EOF &&
     -+		global	user.global=true
     -+		global	user.override=global
     -+		global	include.path=$INCLUDE_DIR/absolute.include
     -+		global	user.absolute=include
     -+		local	user.local=true
     -+		local	user.override=local
     -+		local	include.path=../include/relative.include
     -+		local	user.relative=include
     -+		command	user.cmdline=true
     ++	global	user.global=true
     ++	global	user.override=global
     ++	global	include.path=$INCLUDE_DIR/absolute.include
     ++	global	user.absolute=include
     ++	local	user.local=true
     ++	local	user.override=local
     ++	local	include.path=../include/relative.include
     ++	local	user.relative=include
     ++	command	user.cmdline=true
      +	EOF
      +	git -c user.cmdline=true config --list --show-scope >output &&
      +	test_cmp expect output
     @@ -340,7 +341,7 @@
      +test_expect_success !MINGW '--show-scope with --blob' '
      +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
      +	cat >expect <<-EOF &&
     -+		command	user.custom=true
     ++	command	user.custom=true
      +	EOF
      +	git config --blob=$blob --show-scope --list >output &&
      +	test_cmp expect output
     @@ -348,9 +349,9 @@
      +
      +test_expect_success '--show-scope with --local' '
      +	cat >expect <<-\EOF &&
     -+		local	user.local=true
     -+		local	user.override=local
     -+		local	include.path=../include/relative.include
     ++	local	user.local=true
     ++	local	user.override=local
     ++	local	include.path=../include/relative.include
      +	EOF
      +	git config --local --list --show-scope >output &&
      +	test_cmp expect output
     @@ -358,7 +359,7 @@
      +
      +test_expect_success '--show-scope getting a single value' '
      +	cat >expect <<-\EOF &&
     -+		local	true
     ++	local	true
      +	EOF
      +	git config --show-scope --get user.local >output &&
      +	test_cmp expect output
     @@ -366,15 +367,15 @@
      +
      +test_expect_success '--show-scope with --show-origin' '
      +	cat >expect <<-EOF &&
     -+		global	file:$HOME/.gitconfig	user.global=true
     -+		global	file:$HOME/.gitconfig	user.override=global
     -+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     -+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     -+		local	file:.git/config	user.local=true
     -+		local	file:.git/config	user.override=local
     -+		local	file:.git/config	include.path=../include/relative.include
     -+		local	file:.git/../include/relative.include	user.relative=include
     -+		command	command line:	user.cmdline=true
     ++	global	file:$HOME/.gitconfig	user.global=true
     ++	global	file:$HOME/.gitconfig	user.override=global
     ++	global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     ++	global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     ++	local	file:.git/config	user.local=true
     ++	local	file:.git/config	user.override=local
     ++	local	file:.git/config	include.path=../include/relative.include
     ++	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 &&
      +	test_cmp expect output

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 1/6] config: fix typo in variable name
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
                             ` (6 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 2/6] t1300: fix over-indented HERE-DOCs
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
                             ` (5 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Prepare for the following patches by removing extraneous indents from
HERE-DOCs used in config tests.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..e8b4575758 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		Qr = value2
+	[V.A]
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.a.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		QR = value2
+	[V.A]
+	QR = value2
 	EOF
 	git config -f testConfig_actual "V.a.R" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "V.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual
@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V "A"]
-		R = v1
-		[K "E"]
-		Y = v1
-		[a "b"]
-		c = v1
-		[d "e"]
-		f = v1
+	[V "A"]
+	R = v1
+	[K "E"]
+	Y = v1
+	[a "b"]
+	c = v1
+	[d "e"]
+	f = v1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V "A"]
-		Qr = v2
-		[K "E"]
-		Qy = v2
-		[a "b"]
-		Qc = v2
-		[d "e"]
-		f = v1
-		[d "E"]
-		Qf = v2
+	[V "A"]
+	Qr = v2
+	[K "E"]
+	Qy = v2
+	[a "b"]
+	Qc = v2
+	[d "e"]
+	f = v1
+	[d "E"]
+	Qf = v2
 	EOF
 	# exact match
 	git config -f testConfig_actual a.b.c v2 &&
@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '
 	INCLUDE_DIR="$HOME/include" &&
 	mkdir -p "$INCLUDE_DIR" &&
 	cat >"$INCLUDE_DIR"/absolute.include <<-\EOF &&
-		[user]
-			absolute = include
+	[user]
+		absolute = include
 	EOF
 	cat >"$INCLUDE_DIR"/relative.include <<-\EOF &&
-		[user]
-			relative = include
+	[user]
+		relative = include
 	EOF
 	cat >"$HOME"/.gitconfig <<-EOF &&
-		[user]
-			global = true
-			override = global
-		[include]
-			path = "$INCLUDE_DIR/absolute.include"
+	[user]
+		global = true
+		override = global
+	[include]
+		path = "$INCLUDE_DIR/absolute.include"
 	EOF
 	cat >.git/config <<-\EOF
-		[user]
-			local = true
-			override = local
-		[include]
-			path = ../include/relative.include
+	[user]
+		local = true
+		override = local
+	[include]
+		path = ../include/relative.include
 	EOF
 '
 
 test_expect_success '--show-origin with --list' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global=true
-		file:$HOME/.gitconfig	user.override=global
-		file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
-		file:$INCLUDE_DIR/absolute.include	user.absolute=include
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
-		file:.git/../include/relative.include	user.relative=include
-		command line:	user.cmdline=true
+	file:$HOME/.gitconfig	user.global=true
+	file:$HOME/.gitconfig	user.override=global
+	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
+	file:.git/../include/relative.include	user.relative=include
+	command line:	user.cmdline=true
 	EOF
 	git -c user.cmdline=true config --list --show-origin >output &&
 	test_cmp expect output
@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '
 
 test_expect_success '--show-origin with --list --null' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfigQuser.global
-		trueQfile:$HOME/.gitconfigQuser.override
-		globalQfile:$HOME/.gitconfigQinclude.path
-		$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
-		includeQfile:.git/configQuser.local
-		trueQfile:.git/configQuser.override
-		localQfile:.git/configQinclude.path
-		../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
-		includeQcommand line:Quser.cmdline
-		trueQ
+	file:$HOME/.gitconfigQuser.global
+	trueQfile:$HOME/.gitconfigQuser.override
+	globalQfile:$HOME/.gitconfigQinclude.path
+	$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
+	includeQfile:.git/configQuser.local
+	trueQfile:.git/configQuser.override
+	localQfile:.git/configQinclude.path
+	../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
+	includeQcommand line:Quser.cmdline
+	trueQ
 	EOF
 	git -c user.cmdline=true config --null --list --show-origin >output.raw &&
 	nul_to_q <output.raw >output &&
@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '
 
 test_expect_success '--show-origin with single file' '
 	cat >expect <<-\EOF &&
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
 	EOF
 	git config --local --list --show-origin >output &&
 	test_cmp expect output
@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '
 
 test_expect_success '--show-origin with --get-regexp' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global true
-		file:.git/config	user.local true
+	file:$HOME/.gitconfig	user.global true
+	file:.git/config	user.local true
 	EOF
 	git config --show-origin --get-regexp "user\.[g|l].*" >output &&
 	test_cmp expect output
@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '
 
 test_expect_success '--show-origin getting a single key' '
 	cat >expect <<-\EOF &&
-		file:.git/config	local
+	file:.git/config	local
 	EOF
 	git config --show-origin user.override >output &&
 	test_cmp expect output
@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '
 test_expect_success 'set up custom config file' '
 	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
-		[user]
-			custom = true
+	[user]
+		custom = true
 	EOF
 '
 
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
-		file:"file\" (dq) and spaces.conf"	user.custom=true
+	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
 	test_cmp expect output
@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '
 
 test_expect_success '--show-origin stdin' '
 	cat >expect <<-\EOF &&
-		standard input:	user.custom=true
+	standard input:	user.custom=true
 	EOF
 	git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
 	test_cmp expect output
@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '
 
 test_expect_success '--show-origin stdin with file include' '
 	cat >"$INCLUDE_DIR"/stdin.include <<-EOF &&
-		[user]
-			stdin = include
+	[user]
+		stdin = include
 	EOF
 	cat >expect <<-EOF &&
-		file:$INCLUDE_DIR/stdin.include	include
+	file:$INCLUDE_DIR/stdin.include	include
 	EOF
 	echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" |
 	git config --show-origin --includes --file - user.stdin >output &&
@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '
 test_expect_success !MINGW '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
-		blob:$blob	user.custom=true
+	blob:$blob	user.custom=true
 	EOF
 	git config --blob=$blob --show-origin --list >output &&
 	test_cmp expect output
@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '
 
 test_expect_success !MINGW '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-		blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 3/6] t1300: create custom config file without special characters
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
                             ` (4 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Tests that required a custom configuration file to be created previously
used a file with non-alphanumeric characters including escaped double
quotes.  This is not really necessary for the majority of tests
involving custom config files, and decreases test coverage on systems
that dissallow such filenames (Windows, etc.).

Create two files, one appropriate for testing quoting and one
appropriate for general use.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t1300-config.sh | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e8b4575758..e5fb9114f6 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '
 '
 
 test_expect_success 'set up custom config file' '
-	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
+	CUSTOM_CONFIG_FILE="custom.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
 	[user]
 		custom = true
 	EOF
 '
 
+test_expect_success !MINGW 'set up custom config file with special name characters' '
+	WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" &&
+	cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE"
+'
+
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
 	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
-	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
+	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
 	test_cmp expect output
 '
 
@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob' '
+test_expect_success '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
 	blob:$blob	user.custom=true
@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob ref' '
+test_expect_success '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:master:custom.conf	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 4/6] config: split repo scope to local and worktree
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                             ` (2 preceding siblings ...)
  2020-01-29  3:34           ` [PATCH v6 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                             ` (3 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases, but future functionality may care whether or not the config
options come from a worktree or from the repository's actual local
config file.  For example, the planned feature to add a '--show-scope'
to config to allow a user to see which scope listed config options come
from would confuse users if it just printed 'repo' rather than 'local'
or 'worktree' as the documentation would lead them to expect.  As well
as the additional benefit of making the implementation look more like
how the documentation describes the interface.

To accomplish this we split out what was previously considered repo
scope to be local and worktree.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 6 ++++--
 t/t1308-config-set.sh  | 2 +-
 upload-pack.c          | 3 ++-
 6 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..9c6ae7a8a7 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
-		return "repo";
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7b4e1a63eb..90196e2862 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-repo
 	origin=file
 	name=.git/config
-	scope=repo
+	scope=local
 
 	key=foo.bar
 	value=from-cmdline
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 5/6] config: clarify meaning of command line scoping
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                             ` (3 preceding siblings ...)
  2020-01-29  3:34           ` [PATCH v6 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  3:34           ` [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
                             ` (2 subsequent siblings)
  7 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  Options passed in using this
mechanism share similar scoping characteristics with the --file and
--blob options of the 'config' command, namely that they are only in use
for that single invocation of git, and that they supersede the normal
system/global/local hierarchy.  This patch introduces
CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
CONFIG_SCOPE_CMDLINE redundant.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 t/t1308-config-set.sh  | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 9c6ae7a8a7..56c1f6dfb6 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "local";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 90196e2862..fba0abe429 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=cmdline
+	scope=command
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                             ` (4 preceding siblings ...)
  2020-01-29  3:34           ` [PATCH v6 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-01-29  3:34           ` Matthew Rogers via GitGitGadget
  2020-01-29  9:08             ` Bert Wesarg
  2020-01-29  5:29           ` [PATCH v6 0/6] config: allow user to know scope of config options Junio C Hamano
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
  7 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-01-29  3:34 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-config.txt | 15 ++++++---
 builtin/config.c             | 36 +++++++++++++++++++---
 config.c                     | 26 +++++++++++++++-
 config.h                     | 21 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       | 19 +-----------
 t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
 7 files changed, 141 insertions(+), 39 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..7573160f21 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..ee4aef6a35 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = config_scope_name(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +227,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..18a6bdd9ff 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)
 	}
 }
 
+const char *config_scope_name(enum config_scope scope)
+{
+	switch (scope) {
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
 const char *current_config_name(void)
 {
 	const char *name;
diff --git a/config.h b/config.h
index f383a71404..fe0addb0dc 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,22 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+const char *config_scope_name(enum config_scope scope);
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 56c1f6dfb6..1e3bc7c8f4 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -37,23 +37,6 @@
  *
  */
 
-static const char *scope_name(enum config_scope scope)
-{
-	switch (scope) {
-	case CONFIG_SCOPE_SYSTEM:
-		return "system";
-	case CONFIG_SCOPE_GLOBAL:
-		return "global";
-	case CONFIG_SCOPE_LOCAL:
-		return "local";
-	case CONFIG_SCOPE_WORKTREE:
-		return "worktree";
-	case CONFIG_SCOPE_COMMAND:
-		return "command";
-	default:
-		return "unknown";
-	}
-}
 static int iterate_cb(const char *var, const char *value, void *data)
 {
 	static int nr;
@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
 	printf("value=%s\n", value ? value : "(null)");
 	printf("origin=%s\n", current_config_origin_type());
 	printf("name=%s\n", current_config_name());
-	printf("scope=%s\n", scope_name(current_config_scope()));
+	printf("scope=%s\n", config_scope_name(current_config_scope()));
 
 	return 0;
 }
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e5fb9114f6..5464c46c18 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+	global	user.global=true
+	global	user.override=global
+	global	include.path=$INCLUDE_DIR/absolute.include
+	global	user.absolute=include
+	local	user.local=true
+	local	user.override=local
+	local	include.path=../include/relative.include
+	local	user.relative=include
+	command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+	command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+	local	user.local=true
+	local	user.override=local
+	local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope getting a single value' '
+	cat >expect <<-\EOF &&
+	local	true
+	EOF
+	git config --show-scope --get user.local >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+	global	file:$HOME/.gitconfig	user.global=true
+	global	file:$HOME/.gitconfig	user.override=global
+	global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	local	file:.git/config	user.local=true
+	local	file:.git/config	user.override=local
+	local	file:.git/config	include.path=../include/relative.include
+	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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v6 0/6] config: allow user to know scope of config options
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                             ` (5 preceding siblings ...)
  2020-01-29  3:34           ` [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-29  5:29           ` Junio C Hamano
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
  7 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-01-29  5:29 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> This was originally a pull request to the git-for-windows repository
> [https://github.com/git-for-windows/git/pull/2399]. It adds a new option
> --show-scope which would allow a user to see what scope a given
> configuration value has (sytem, local, global, etc.).
>
> changes since v4:
>
>  * final cleanups

Indeed.  This round looks good.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-29  3:34           ` [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
@ 2020-01-29  9:08             ` Bert Wesarg
  2020-01-29 23:03               ` Matt Rogers
  0 siblings, 1 reply; 98+ messages in thread
From: Bert Wesarg @ 2020-01-29  9:08 UTC (permalink / raw)
  To: Matthew Rogers; +Cc: Matthew Rogers via GitGitGadget, git

Dear Matthew,

On 29.01.20 04:34, Matthew Rogers via GitGitGadget wrote:
> From: Matthew Rogers <mattr94@gmail.com>
> 
> When a user queries config values with --show-origin, often it's
> difficult to determine what the actual "scope" (local, global, etc.) of
> a given value is based on just the origin file.
> 
> Teach 'git config' the '--show-scope' option to print the scope of all
> displayed config values.  Note that we should never see anything of
> "submodule" scope as that is only ever used by submodule-config.c when
> parsing the '.gitmodules' file.
> 
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>   Documentation/git-config.txt | 15 ++++++---
>   builtin/config.c             | 36 +++++++++++++++++++---
>   config.c                     | 26 +++++++++++++++-
>   config.h                     | 21 +++++++------
>   submodule-config.c           |  4 ++-
>   t/helper/test-config.c       | 19 +-----------
>   t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
>   7 files changed, 141 insertions(+), 39 deletions(-)

for clarity, I think this patch should be split up further.

For example:

  - moving an enum and adding a new entry should be avoided
  - does the changes to '/config.c' fix something?
  - exposing config_scope_name should have been done before PATCH 4/6 already

Best,
Bert

> 
> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
> index 899e92a1c9..7573160f21 100644
> --- a/Documentation/git-config.txt
> +++ b/Documentation/git-config.txt
> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options
>   SYNOPSIS
>   --------
>   [verse]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
>   'git config' [<file-option>] [--type=<type>] --add name value
>   'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
>   'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
>   'git config' [<file-option>] --unset name [value_regex]
>   'git config' [<file-option>] --unset-all name [value_regex]
>   'git config' [<file-option>] --rename-section old_name new_name
>   'git config' [<file-option>] --remove-section name
> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
> +'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
> @@ -222,6 +222,11 @@ Valid `<type>`'s include:
>   	the actual origin (config file path, ref, or blob id if
>   	applicable).
>   
> +--show-scope::
> +	Similar to `--show-origin` in that it augments the output of
> +	all queried config options with the scope of that value
> +	(local, global, system, command).
> +
>   --get-colorbool name [stdout-is-tty]::
>   
>   	Find the color setting for `name` (e.g. `color.diff`) and output
> diff --git a/builtin/config.c b/builtin/config.c
> index 52a904cfb1..ee4aef6a35 100644
> --- a/builtin/config.c
> +++ b/builtin/config.c
> @@ -33,6 +33,7 @@ static int end_nul;
>   static int respect_includes_opt = -1;
>   static struct config_options config_options;
>   static int show_origin;
> +static int show_scope;
>   
>   #define ACTION_GET (1<<0)
>   #define ACTION_GET_ALL (1<<1)
> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
>   	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
>   	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
>   	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
> +	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
>   	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
>   	OPT_END(),
>   };
> @@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)
>   	strbuf_addch(buf, term);
>   }
>   
> +static void show_config_scope(struct strbuf *buf)
> +{
> +	const char term = end_nul ? '\0' : '\t';
> +	const char *scope = config_scope_name(current_config_scope());
> +
> +	strbuf_addstr(buf, N_(scope));
> +	strbuf_addch(buf, term);
> +}
> +
>   static int show_all_config(const char *key_, const char *value_, void *cb)
>   {
> -	if (show_origin) {
> +	if (show_origin || show_scope) {
>   		struct strbuf buf = STRBUF_INIT;
> -		show_config_origin(&buf);
> +		if (show_scope)
> +			show_config_scope(&buf);
> +		if (show_origin)
> +			show_config_origin(&buf);
>   		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
>   		fwrite(buf.buf, 1, buf.len, stdout);
>   		strbuf_release(&buf);
> @@ -213,6 +227,8 @@ struct strbuf_list {
>   
>   static int format_config(struct strbuf *buf, const char *key_, const char *value_)
>   {
> +	if (show_scope)
> +		show_config_scope(buf);
>   	if (show_origin)
>   		show_config_origin(buf);
>   	if (show_keys)
> @@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>   			!strcmp(given_config_source.file, "-")) {
>   		given_config_source.file = NULL;
>   		given_config_source.use_stdin = 1;
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;
>   	}
>   
>   	if (use_global_config) {
> @@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>   			 */
>   			die(_("$HOME not set"));
>   
> +		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
> +
>   		if (access_or_warn(user_config, R_OK, 0) &&
>   		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
>   			given_config_source.file = xdg_config;
> @@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>   			free(xdg_config);
>   		}
>   	}
> -	else if (use_system_config)
> +	else if (use_system_config) {
>   		given_config_source.file = git_etc_gitconfig();
> -	else if (use_local_config)
> +		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
> +	} else if (use_local_config) {
>   		given_config_source.file = git_pathdup("config");
> -	else if (use_worktree_config) {
> +		given_config_source.scope = CONFIG_SCOPE_LOCAL;
> +	} else if (use_worktree_config) {
>   		struct worktree **worktrees = get_worktrees(0);
>   		if (repository_format_worktree_config)
>   			given_config_source.file = git_pathdup("config.worktree");
> @@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
>   			      "section in \"git help worktree\" for details"));
>   		else
>   			given_config_source.file = git_pathdup("config");
> +		given_config_source.scope = CONFIG_SCOPE_LOCAL;
>   		free_worktrees(worktrees);
>   	} else if (given_config_source.file) {
>   		if (!is_absolute_path(given_config_source.file) && prefix)
>   			given_config_source.file =
>   				prefix_filename(prefix, given_config_source.file);
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;
> +	} else if (given_config_source.blob) {
> +		given_config_source.scope = CONFIG_SCOPE_COMMAND;
>   	}
>   
> +
>   	if (respect_includes_opt == -1)
>   		config_options.respect_includes = !given_config_source.file;
>   	else
> diff --git a/config.c b/config.c
> index f319a3d6a0..18a6bdd9ff 100644
> --- a/config.c
> +++ b/config.c
> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>   	char *xdg_config = xdg_config_home("config");
>   	char *user_config = expand_user_path("~/.gitconfig", 0);
>   	char *repo_config;
> +	enum config_scope prev_parsing_scope = current_parsing_scope;
>   
>   	if (opts->commondir)
>   		repo_config = mkpathdup("%s/config", opts->commondir);
> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>   	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
>   		die(_("unable to parse command-line config"));
>   
> -	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
> +	current_parsing_scope = prev_parsing_scope;
>   	free(xdg_config);
>   	free(user_config);
>   	free(repo_config);
> @@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
>   		data = &inc;
>   	}
>   
> +	if (config_source)
> +		current_parsing_scope = config_source->scope;
> +
>   	/*
>   	 * If we have a specific filename, use it. Otherwise, follow the
>   	 * regular lookup sequence.
> @@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)
>   	}
>   }
>   
> +const char *config_scope_name(enum config_scope scope)
> +{
> +	switch (scope) {
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
> +	default:
> +		return "unknown";
> +	}
> +}
> +
>   const char *current_config_name(void)
>   {
>   	const char *name;
> diff --git a/config.h b/config.h
> index f383a71404..fe0addb0dc 100644
> --- a/config.h
> +++ b/config.h
> @@ -35,10 +35,22 @@ struct object_id;
>   
>   #define CONFIG_REGEX_NONE ((void *)1)
>   
> +enum config_scope {
> +	CONFIG_SCOPE_UNKNOWN = 0,
> +	CONFIG_SCOPE_SYSTEM,
> +	CONFIG_SCOPE_GLOBAL,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
> +	CONFIG_SCOPE_COMMAND,
> +	CONFIG_SCOPE_SUBMODULE,
> +};
> +const char *config_scope_name(enum config_scope scope);
> +
>   struct git_config_source {
>   	unsigned int use_stdin:1;
>   	const char *file;
>   	const char *blob;
> +	enum config_scope scope;
>   };
>   
>   enum config_origin_type {
> @@ -294,15 +306,6 @@ int config_error_nonbool(const char *);
>   
>   int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
>   
> -enum config_scope {
> -	CONFIG_SCOPE_UNKNOWN = 0,
> -	CONFIG_SCOPE_SYSTEM,
> -	CONFIG_SCOPE_GLOBAL,
> -	CONFIG_SCOPE_LOCAL,
> -	CONFIG_SCOPE_WORKTREE,
> -	CONFIG_SCOPE_COMMAND,
> -};
> -
>   enum config_scope current_config_scope(void);
>   const char *current_config_origin_type(void);
>   const char *current_config_name(void);
> diff --git a/submodule-config.c b/submodule-config.c
> index 85064810b2..b8e97d8ae8 100644
> --- a/submodule-config.c
> +++ b/submodule-config.c
> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
>   static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
>   {
>   	if (repo->worktree) {
> -		struct git_config_source config_source = { 0 };
> +		struct git_config_source config_source = {
> +			0, .scope = CONFIG_SCOPE_SUBMODULE
> +		};
>   		const struct config_options opts = { 0 };
>   		struct object_id oid;
>   		char *file;
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 56c1f6dfb6..1e3bc7c8f4 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -37,23 +37,6 @@
>    *
>    */
>   
> -static const char *scope_name(enum config_scope scope)
> -{
> -	switch (scope) {
> -	case CONFIG_SCOPE_SYSTEM:
> -		return "system";
> -	case CONFIG_SCOPE_GLOBAL:
> -		return "global";
> -	case CONFIG_SCOPE_LOCAL:
> -		return "local";
> -	case CONFIG_SCOPE_WORKTREE:
> -		return "worktree";
> -	case CONFIG_SCOPE_COMMAND:
> -		return "command";
> -	default:
> -		return "unknown";
> -	}
> -}
>   static int iterate_cb(const char *var, const char *value, void *data)
>   {
>   	static int nr;
> @@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
>   	printf("value=%s\n", value ? value : "(null)");
>   	printf("origin=%s\n", current_config_origin_type());
>   	printf("name=%s\n", current_config_name());
> -	printf("scope=%s\n", scope_name(current_config_scope()));
> +	printf("scope=%s\n", config_scope_name(current_config_scope()));
>   
>   	return 0;
>   }
> diff --git a/t/t1300-config.sh b/t/t1300-config.sh
> index e5fb9114f6..5464c46c18 100755
> --- a/t/t1300-config.sh
> +++ b/t/t1300-config.sh
> @@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
>   	test_cmp expect output
>   '
>   
> +test_expect_success '--show-scope with --list' '
> +	cat >expect <<-EOF &&
> +	global	user.global=true
> +	global	user.override=global
> +	global	include.path=$INCLUDE_DIR/absolute.include
> +	global	user.absolute=include
> +	local	user.local=true
> +	local	user.override=local
> +	local	include.path=../include/relative.include
> +	local	user.relative=include
> +	command	user.cmdline=true
> +	EOF
> +	git -c user.cmdline=true config --list --show-scope >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success !MINGW '--show-scope with --blob' '
> +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
> +	cat >expect <<-EOF &&
> +	command	user.custom=true
> +	EOF
> +	git config --blob=$blob --show-scope --list >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success '--show-scope with --local' '
> +	cat >expect <<-\EOF &&
> +	local	user.local=true
> +	local	user.override=local
> +	local	include.path=../include/relative.include
> +	EOF
> +	git config --local --list --show-scope >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success '--show-scope getting a single value' '
> +	cat >expect <<-\EOF &&
> +	local	true
> +	EOF
> +	git config --show-scope --get user.local >output &&
> +	test_cmp expect output
> +'
> +
> +test_expect_success '--show-scope with --show-origin' '
> +	cat >expect <<-EOF &&
> +	global	file:$HOME/.gitconfig	user.global=true
> +	global	file:$HOME/.gitconfig	user.override=global
> +	global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
> +	global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
> +	local	file:.git/config	user.local=true
> +	local	file:.git/config	user.override=local
> +	local	file:.git/config	include.path=../include/relative.include
> +	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 &&
> +	test_cmp expect output
> +'
> +
>   test_expect_success '--local requires a repo' '
>   	# we expect 128 to ensure that we do not simply
>   	# fail to find anything and return code "1"
> 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-29  9:08             ` Bert Wesarg
@ 2020-01-29 23:03               ` Matt Rogers
  2020-02-05 19:01                 ` Junio C Hamano
  0 siblings, 1 reply; 98+ messages in thread
From: Matt Rogers @ 2020-01-29 23:03 UTC (permalink / raw)
  To: Bert Wesarg; +Cc: Matthew Rogers via GitGitGadget, Git Mailing List

>
> for clarity, I think this patch should be split up further.
>
> For example:
>
>   - moving an enum and adding a new entry should be avoided

As far as adding a new entry, that could probably be done in a separate patch.
The submodule scoping is correct (mostly so config options that come from
submodule blobs have a sane value to set the new scope field of
git_config_source), but moving it is unavoidable as I'd either have to move
config_scope or git_config_source for this patch to work, and moving
git_config_source seemed like a ton more work

>   - does the changes to '/config.c' fix something?

Another thing, that in hindsight could probably be split out. The other changes
do fix the fact that previously recursive calls to do_git_config_sequence()
would blow awway the current_parsing_scope information for higher level callers.
This is not super common, but does occur when --show-scope is used with the
--blob option.

>   - exposing config_scope_name should have been done before PATCH 4/6 already

If that's better/more convenient, I don't have a problem breaking that
out and moving
it there.


-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value
  2020-01-29 23:03               ` Matt Rogers
@ 2020-02-05 19:01                 ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-05 19:01 UTC (permalink / raw)
  To: Matt Rogers
  Cc: Bert Wesarg, Matthew Rogers via GitGitGadget, Git Mailing List

Matt Rogers <mattr94@gmail.com> writes:

>> for clarity, I think this patch should be split up further.
>>
>> For example:
>>
>>   - moving an enum and adding a new entry should be avoided
>
> As far as adding a new entry, that could probably be done in a separate patch.
> The submodule scoping is correct (mostly so config options that come from
> submodule blobs have a sane value to set the new scope field of
> git_config_source), but moving it is unavoidable as I'd either have to move
> config_scope or git_config_source for this patch to work, and moving
> git_config_source seemed like a ton more work
>
>>   - does the changes to '/config.c' fix something?
>
> Another thing, that in hindsight could probably be split out. The other changes
> do fix the fact that previously recursive calls to do_git_config_sequence()
> would blow awway the current_parsing_scope information for higher level callers.
> This is not super common, but does occur when --show-scope is used with the
> --blob option.
>
>>   - exposing config_scope_name should have been done before PATCH 4/6 already
>
> If that's better/more convenient, I don't have a problem breaking that
> out and moving
> it there.

Alright.  Thanks for another round of review.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 00/10] config: allow user to know scope of config options
  2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
                             ` (6 preceding siblings ...)
  2020-01-29  5:29           ` [PATCH v6 0/6] config: allow user to know scope of config options Junio C Hamano
@ 2020-02-10  0:30           ` " Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 01/10] config: fix typo in variable name Matthew Rogers via GitGitGadget
                               ` (9 more replies)
  7 siblings, 10 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v6: Split patch 6: config: add '--show-scope'... into several
parts, including moving the exposure of config_scope_name into its own
commit earlier in the series.

Matthew Rogers (10):
  config: fix typo in variable name
  t1300: fix over-indented HERE-DOCs
  t1300: create custom config file without special characters
  config: make scope_name non-static and rename it
  config: split repo scope to local and worktree
  config: clarify meaning of command line scoping
  config: preserve scope in do_git_config_sequence
  config: teach git_config_source to remember its scope
  submodule-config: add subomdule config scope
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt |  15 ++-
 builtin/config.c             |  46 +++++--
 config.c                     |  35 ++++-
 config.h                     |  20 +--
 remote.c                     |   3 +-
 submodule-config.c           |   4 +-
 t/helper/test-config.c       |  17 +--
 t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------
 t/t1308-config-set.sh        |   4 +-
 upload-pack.c                |   3 +-
 10 files changed, 248 insertions(+), 139 deletions(-)


base-commit: de93cc14ab7e8db7645d8dbe4fd2603f76d5851f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v7
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v7
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v6:

  1:  18f92f70cf =  1:  1c4faa7a36 config: fix typo in variable name
  2:  dc7b3f3b96 =  2:  2c38c72f89 t1300: fix over-indented HERE-DOCs
  3:  975e652368 =  3:  c832293ca7 t1300: create custom config file without special characters
  -:  ---------- >  4:  14b0f27819 config: make scope_name non-static and rename it
  4:  1e406ba430 !  5:  1af0237b8e config: split repo scope to local and worktree
     @@ -45,6 +45,19 @@
       	if (!opts->ignore_worktree && repository_format_worktree_config) {
       		char *path = git_pathdup("config.worktree");
       		if (!access_or_die(path, R_OK, 0))
     +@@
     + 		return "system";
     + 	case CONFIG_SCOPE_GLOBAL:
     + 		return "global";
     +-	case CONFIG_SCOPE_REPO:
     +-		return "repo";
     ++	case CONFIG_SCOPE_LOCAL:
     ++		return "local";
     ++	case CONFIG_SCOPE_WORKTREE:
     ++		return "worktree";
     + 	case CONFIG_SCOPE_CMDLINE:
     + 		return "command line";
     + 	default:
      
       diff --git a/config.h b/config.h
       --- a/config.h
     @@ -58,7 +71,7 @@
      +	CONFIG_SCOPE_WORKTREE,
       	CONFIG_SCOPE_CMDLINE,
       };
     - 
     + const char *config_scope_name(enum config_scope scope);
      
       diff --git a/remote.c b/remote.c
       --- a/remote.c
     @@ -74,23 +87,6 @@
       	if (!strcmp(subkey, "mirror"))
       		remote->mirror = git_config_bool(key, value);
      
     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c
     - --- a/t/helper/test-config.c
     - +++ b/t/helper/test-config.c
     -@@
     - 		return "system";
     - 	case CONFIG_SCOPE_GLOBAL:
     - 		return "global";
     --	case CONFIG_SCOPE_REPO:
     --		return "repo";
     -+	case CONFIG_SCOPE_LOCAL:
     -+		return "local";
     -+	case CONFIG_SCOPE_WORKTREE:
     -+		return "worktree";
     - 	case CONFIG_SCOPE_CMDLINE:
     - 		return "cmdline";
     - 	default:
     -
       diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
       --- a/t/t1308-config-set.sh
       +++ b/t/t1308-config-set.sh
  5:  936ce91c62 !  6:  64c20d0556 config: clarify meaning of command line scoping
     @@ -26,6 +26,17 @@
       	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
       		die(_("unable to parse command-line config"));
       
     +@@
     + 		return "local";
     + 	case CONFIG_SCOPE_WORKTREE:
     + 		return "worktree";
     +-	case CONFIG_SCOPE_CMDLINE:
     +-		return "command line";
     ++	case CONFIG_SCOPE_COMMAND:
     ++		return "command";
     + 	default:
     + 		return "unknown";
     + 	}
      
       diff --git a/config.h b/config.h
       --- a/config.h
     @@ -37,23 +48,8 @@
      -	CONFIG_SCOPE_CMDLINE,
      +	CONFIG_SCOPE_COMMAND,
       };
     + const char *config_scope_name(enum config_scope scope);
       
     - enum config_scope current_config_scope(void);
     -
     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c
     - --- a/t/helper/test-config.c
     - +++ b/t/helper/test-config.c
     -@@
     - 		return "local";
     - 	case CONFIG_SCOPE_WORKTREE:
     - 		return "worktree";
     --	case CONFIG_SCOPE_CMDLINE:
     --		return "cmdline";
     -+	case CONFIG_SCOPE_COMMAND:
     -+		return "command";
     - 	default:
     - 		return "unknown";
     - 	}
      
       diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
       --- a/t/t1308-config-set.sh
     @@ -62,7 +58,7 @@
       	value=from-cmdline
       	origin=command line
       	name=
     --	scope=cmdline
     +-	scope=command line
      +	scope=command
       	EOF
       	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
  -:  ---------- >  7:  f61985375c config: preserve scope in do_git_config_sequence
  -:  ---------- >  8:  6c59c5cace config: teach git_config_source to remember its scope
  -:  ---------- >  9:  dd376246ec submodule-config: add subomdule config scope
  6:  fc141e8689 ! 10:  f76463ee90 config: add '--show-scope' to print the scope of a config value
     @@ -12,7 +12,6 @@
          parsing the '.gitmodules' file.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
      
       diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
       --- a/Documentation/git-config.txt
     @@ -108,212 +107,6 @@
       	if (show_origin)
       		show_config_origin(buf);
       	if (show_keys)
     -@@
     - 			!strcmp(given_config_source.file, "-")) {
     - 		given_config_source.file = NULL;
     - 		given_config_source.use_stdin = 1;
     -+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     - 	}
     - 
     - 	if (use_global_config) {
     -@@
     - 			 */
     - 			die(_("$HOME not set"));
     - 
     -+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
     -+
     - 		if (access_or_warn(user_config, R_OK, 0) &&
     - 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
     - 			given_config_source.file = xdg_config;
     -@@
     - 			free(xdg_config);
     - 		}
     - 	}
     --	else if (use_system_config)
     -+	else if (use_system_config) {
     - 		given_config_source.file = git_etc_gitconfig();
     --	else if (use_local_config)
     -+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
     -+	} else if (use_local_config) {
     - 		given_config_source.file = git_pathdup("config");
     --	else if (use_worktree_config) {
     -+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     -+	} else if (use_worktree_config) {
     - 		struct worktree **worktrees = get_worktrees(0);
     - 		if (repository_format_worktree_config)
     - 			given_config_source.file = git_pathdup("config.worktree");
     -@@
     - 			      "section in \"git help worktree\" for details"));
     - 		else
     - 			given_config_source.file = git_pathdup("config");
     -+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     - 		free_worktrees(worktrees);
     - 	} else if (given_config_source.file) {
     - 		if (!is_absolute_path(given_config_source.file) && prefix)
     - 			given_config_source.file =
     - 				prefix_filename(prefix, given_config_source.file);
     -+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     -+	} else if (given_config_source.blob) {
     -+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     - 	}
     - 
     -+
     - 	if (respect_includes_opt == -1)
     - 		config_options.respect_includes = !given_config_source.file;
     - 	else
     -
     - diff --git a/config.c b/config.c
     - --- a/config.c
     - +++ b/config.c
     -@@
     - 	char *xdg_config = xdg_config_home("config");
     - 	char *user_config = expand_user_path("~/.gitconfig", 0);
     - 	char *repo_config;
     -+	enum config_scope prev_parsing_scope = current_parsing_scope;
     - 
     - 	if (opts->commondir)
     - 		repo_config = mkpathdup("%s/config", opts->commondir);
     -@@
     - 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
     - 		die(_("unable to parse command-line config"));
     - 
     --	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
     -+	current_parsing_scope = prev_parsing_scope;
     - 	free(xdg_config);
     - 	free(user_config);
     - 	free(repo_config);
     -@@
     - 		data = &inc;
     - 	}
     - 
     -+	if (config_source)
     -+		current_parsing_scope = config_source->scope;
     -+
     - 	/*
     - 	 * If we have a specific filename, use it. Otherwise, follow the
     - 	 * regular lookup sequence.
     -@@
     - 	}
     - }
     - 
     -+const char *config_scope_name(enum config_scope scope)
     -+{
     -+	switch (scope) {
     -+	case CONFIG_SCOPE_SYSTEM:
     -+		return "system";
     -+	case CONFIG_SCOPE_GLOBAL:
     -+		return "global";
     -+	case CONFIG_SCOPE_LOCAL:
     -+		return "local";
     -+	case CONFIG_SCOPE_WORKTREE:
     -+		return "worktree";
     -+	case CONFIG_SCOPE_COMMAND:
     -+		return "command";
     -+	case CONFIG_SCOPE_SUBMODULE:
     -+		return "submodule";
     -+	default:
     -+		return "unknown";
     -+	}
     -+}
     -+
     - const char *current_config_name(void)
     - {
     - 	const char *name;
     -
     - diff --git a/config.h b/config.h
     - --- a/config.h
     - +++ b/config.h
     -@@
     - 
     - #define CONFIG_REGEX_NONE ((void *)1)
     - 
     -+enum config_scope {
     -+	CONFIG_SCOPE_UNKNOWN = 0,
     -+	CONFIG_SCOPE_SYSTEM,
     -+	CONFIG_SCOPE_GLOBAL,
     -+	CONFIG_SCOPE_LOCAL,
     -+	CONFIG_SCOPE_WORKTREE,
     -+	CONFIG_SCOPE_COMMAND,
     -+	CONFIG_SCOPE_SUBMODULE,
     -+};
     -+const char *config_scope_name(enum config_scope scope);
     -+
     - struct git_config_source {
     - 	unsigned int use_stdin:1;
     - 	const char *file;
     - 	const char *blob;
     -+	enum config_scope scope;
     - };
     - 
     - enum config_origin_type {
     -@@
     - 
     - int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
     - 
     --enum config_scope {
     --	CONFIG_SCOPE_UNKNOWN = 0,
     --	CONFIG_SCOPE_SYSTEM,
     --	CONFIG_SCOPE_GLOBAL,
     --	CONFIG_SCOPE_LOCAL,
     --	CONFIG_SCOPE_WORKTREE,
     --	CONFIG_SCOPE_COMMAND,
     --};
     --
     - enum config_scope current_config_scope(void);
     - const char *current_config_origin_type(void);
     - const char *current_config_name(void);
     -
     - diff --git a/submodule-config.c b/submodule-config.c
     - --- a/submodule-config.c
     - +++ b/submodule-config.c
     -@@
     - static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
     - {
     - 	if (repo->worktree) {
     --		struct git_config_source config_source = { 0 };
     -+		struct git_config_source config_source = {
     -+			0, .scope = CONFIG_SCOPE_SUBMODULE
     -+		};
     - 		const struct config_options opts = { 0 };
     - 		struct object_id oid;
     - 		char *file;
     -
     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c
     - --- a/t/helper/test-config.c
     - +++ b/t/helper/test-config.c
     -@@
     -  *
     -  */
     - 
     --static const char *scope_name(enum config_scope scope)
     --{
     --	switch (scope) {
     --	case CONFIG_SCOPE_SYSTEM:
     --		return "system";
     --	case CONFIG_SCOPE_GLOBAL:
     --		return "global";
     --	case CONFIG_SCOPE_LOCAL:
     --		return "local";
     --	case CONFIG_SCOPE_WORKTREE:
     --		return "worktree";
     --	case CONFIG_SCOPE_COMMAND:
     --		return "command";
     --	default:
     --		return "unknown";
     --	}
     --}
     - static int iterate_cb(const char *var, const char *value, void *data)
     - {
     - 	static int nr;
     -@@
     - 	printf("value=%s\n", value ? value : "(null)");
     - 	printf("origin=%s\n", current_config_origin_type());
     - 	printf("name=%s\n", current_config_name());
     --	printf("scope=%s\n", scope_name(current_config_scope()));
     -+	printf("scope=%s\n", config_scope_name(current_config_scope()));
     - 
     - 	return 0;
     - }
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 01/10] config: fix typo in variable name
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 02/10] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
                               ` (8 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 02/10] t1300: fix over-indented HERE-DOCs
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 01/10] config: fix typo in variable name Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 03/10] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
                               ` (7 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Prepare for the following patches by removing extraneous indents from
HERE-DOCs used in config tests.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------
 1 file changed, 84 insertions(+), 84 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..e8b4575758 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		Qr = value2
+	[V.A]
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.a.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		QR = value2
+	[V.A]
+	QR = value2
 	EOF
 	git config -f testConfig_actual "V.a.R" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "V.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V.A]
-		r = value1
+	[V.A]
+	r = value1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V.A]
-		r = value1
-		Qr = value2
+	[V.A]
+	r = value1
+	Qr = value2
 	EOF
 	git config -f testConfig_actual "v.A.r" value2 &&
 	test_cmp testConfig_expect testConfig_actual
@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '
 	test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
 
 	cat >testConfig_actual <<-EOF &&
-		[V "A"]
-		R = v1
-		[K "E"]
-		Y = v1
-		[a "b"]
-		c = v1
-		[d "e"]
-		f = v1
+	[V "A"]
+	R = v1
+	[K "E"]
+	Y = v1
+	[a "b"]
+	c = v1
+	[d "e"]
+	f = v1
 	EOF
 	q_to_tab >testConfig_expect <<-EOF &&
-		[V "A"]
-		Qr = v2
-		[K "E"]
-		Qy = v2
-		[a "b"]
-		Qc = v2
-		[d "e"]
-		f = v1
-		[d "E"]
-		Qf = v2
+	[V "A"]
+	Qr = v2
+	[K "E"]
+	Qy = v2
+	[a "b"]
+	Qc = v2
+	[d "e"]
+	f = v1
+	[d "E"]
+	Qf = v2
 	EOF
 	# exact match
 	git config -f testConfig_actual a.b.c v2 &&
@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '
 	INCLUDE_DIR="$HOME/include" &&
 	mkdir -p "$INCLUDE_DIR" &&
 	cat >"$INCLUDE_DIR"/absolute.include <<-\EOF &&
-		[user]
-			absolute = include
+	[user]
+		absolute = include
 	EOF
 	cat >"$INCLUDE_DIR"/relative.include <<-\EOF &&
-		[user]
-			relative = include
+	[user]
+		relative = include
 	EOF
 	cat >"$HOME"/.gitconfig <<-EOF &&
-		[user]
-			global = true
-			override = global
-		[include]
-			path = "$INCLUDE_DIR/absolute.include"
+	[user]
+		global = true
+		override = global
+	[include]
+		path = "$INCLUDE_DIR/absolute.include"
 	EOF
 	cat >.git/config <<-\EOF
-		[user]
-			local = true
-			override = local
-		[include]
-			path = ../include/relative.include
+	[user]
+		local = true
+		override = local
+	[include]
+		path = ../include/relative.include
 	EOF
 '
 
 test_expect_success '--show-origin with --list' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global=true
-		file:$HOME/.gitconfig	user.override=global
-		file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
-		file:$INCLUDE_DIR/absolute.include	user.absolute=include
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
-		file:.git/../include/relative.include	user.relative=include
-		command line:	user.cmdline=true
+	file:$HOME/.gitconfig	user.global=true
+	file:$HOME/.gitconfig	user.override=global
+	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
+	file:.git/../include/relative.include	user.relative=include
+	command line:	user.cmdline=true
 	EOF
 	git -c user.cmdline=true config --list --show-origin >output &&
 	test_cmp expect output
@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '
 
 test_expect_success '--show-origin with --list --null' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfigQuser.global
-		trueQfile:$HOME/.gitconfigQuser.override
-		globalQfile:$HOME/.gitconfigQinclude.path
-		$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
-		includeQfile:.git/configQuser.local
-		trueQfile:.git/configQuser.override
-		localQfile:.git/configQinclude.path
-		../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
-		includeQcommand line:Quser.cmdline
-		trueQ
+	file:$HOME/.gitconfigQuser.global
+	trueQfile:$HOME/.gitconfigQuser.override
+	globalQfile:$HOME/.gitconfigQinclude.path
+	$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute
+	includeQfile:.git/configQuser.local
+	trueQfile:.git/configQuser.override
+	localQfile:.git/configQinclude.path
+	../include/relative.includeQfile:.git/../include/relative.includeQuser.relative
+	includeQcommand line:Quser.cmdline
+	trueQ
 	EOF
 	git -c user.cmdline=true config --null --list --show-origin >output.raw &&
 	nul_to_q <output.raw >output &&
@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '
 
 test_expect_success '--show-origin with single file' '
 	cat >expect <<-\EOF &&
-		file:.git/config	user.local=true
-		file:.git/config	user.override=local
-		file:.git/config	include.path=../include/relative.include
+	file:.git/config	user.local=true
+	file:.git/config	user.override=local
+	file:.git/config	include.path=../include/relative.include
 	EOF
 	git config --local --list --show-origin >output &&
 	test_cmp expect output
@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '
 
 test_expect_success '--show-origin with --get-regexp' '
 	cat >expect <<-EOF &&
-		file:$HOME/.gitconfig	user.global true
-		file:.git/config	user.local true
+	file:$HOME/.gitconfig	user.global true
+	file:.git/config	user.local true
 	EOF
 	git config --show-origin --get-regexp "user\.[g|l].*" >output &&
 	test_cmp expect output
@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '
 
 test_expect_success '--show-origin getting a single key' '
 	cat >expect <<-\EOF &&
-		file:.git/config	local
+	file:.git/config	local
 	EOF
 	git config --show-origin user.override >output &&
 	test_cmp expect output
@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '
 test_expect_success 'set up custom config file' '
 	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
-		[user]
-			custom = true
+	[user]
+		custom = true
 	EOF
 '
 
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
-		file:"file\" (dq) and spaces.conf"	user.custom=true
+	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
 	test_cmp expect output
@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '
 
 test_expect_success '--show-origin stdin' '
 	cat >expect <<-\EOF &&
-		standard input:	user.custom=true
+	standard input:	user.custom=true
 	EOF
 	git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
 	test_cmp expect output
@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '
 
 test_expect_success '--show-origin stdin with file include' '
 	cat >"$INCLUDE_DIR"/stdin.include <<-EOF &&
-		[user]
-			stdin = include
+	[user]
+		stdin = include
 	EOF
 	cat >expect <<-EOF &&
-		file:$INCLUDE_DIR/stdin.include	include
+	file:$INCLUDE_DIR/stdin.include	include
 	EOF
 	echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" |
 	git config --show-origin --includes --file - user.stdin >output &&
@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '
 test_expect_success !MINGW '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
-		blob:$blob	user.custom=true
+	blob:$blob	user.custom=true
 	EOF
 	git config --blob=$blob --show-origin --list >output &&
 	test_cmp expect output
@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '
 
 test_expect_success !MINGW '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-		blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 03/10] t1300: create custom config file without special characters
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 01/10] config: fix typo in variable name Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 02/10] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 04/10] config: make scope_name non-static and rename it Matthew Rogers via GitGitGadget
                               ` (6 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Tests that required a custom configuration file to be created previously
used a file with non-alphanumeric characters including escaped double
quotes.  This is not really necessary for the majority of tests
involving custom config files, and decreases test coverage on systems
that dissallow such filenames (Windows, etc.).

Create two files, one appropriate for testing quoting and one
appropriate for general use.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t1300-config.sh | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e8b4575758..e5fb9114f6 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '
 '
 
 test_expect_success 'set up custom config file' '
-	CUSTOM_CONFIG_FILE="file\" (dq) and spaces.conf" &&
+	CUSTOM_CONFIG_FILE="custom.conf" &&
 	cat >"$CUSTOM_CONFIG_FILE" <<-\EOF
 	[user]
 		custom = true
 	EOF
 '
 
+test_expect_success !MINGW 'set up custom config file with special name characters' '
+	WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" &&
+	cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE"
+'
+
 test_expect_success !MINGW '--show-origin escape special file name characters' '
 	cat >expect <<-\EOF &&
 	file:"file\" (dq) and spaces.conf"	user.custom=true
 	EOF
-	git config --file "$CUSTOM_CONFIG_FILE" --show-origin --list >output &&
+	git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
 	test_cmp expect output
 '
 
@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob' '
+test_expect_success '--show-origin blob' '
 	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
 	cat >expect <<-EOF &&
 	blob:$blob	user.custom=true
@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '
 	test_cmp expect output
 '
 
-test_expect_success !MINGW '--show-origin blob ref' '
+test_expect_success '--show-origin blob ref' '
 	cat >expect <<-\EOF &&
-	blob:"master:file\" (dq) and spaces.conf"	user.custom=true
+	blob:master:custom.conf	user.custom=true
 	EOF
 	git add "$CUSTOM_CONFIG_FILE" &&
 	git commit -m "new config file" &&
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (2 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 03/10] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:02               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 05/10] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
                               ` (5 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

To prepare for the upcoming --show-scope option, we require the ability
to convert a config_scope enum to a string.  As this was originally
implemented as a static function 'scope_name()' in
t/helper/test-config.c, we expose it via config.h and give it a less
ambiguous name 'config_scope_name()'

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 16 ++++++++++++++++
 config.h               |  2 ++
 t/helper/test-config.c | 17 +----------------
 t/t1308-config-set.sh  |  2 +-
 4 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..83bb98d65e 100644
--- a/config.c
+++ b/config.c
@@ -3297,6 +3297,22 @@ const char *current_config_origin_type(void)
 	}
 }
 
+const char *config_scope_name(enum config_scope scope)
+{
+	switch (scope) {
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_REPO:
+		return "repo";
+	case CONFIG_SCOPE_CMDLINE:
+		return "command line";
+	default:
+		return "unknown";
+	}
+}
+
 const char *current_config_name(void)
 {
 	const char *name;
diff --git a/config.h b/config.h
index 91fd4c5e96..dcb8c274d4 100644
--- a/config.h
+++ b/config.h
@@ -35,6 +35,7 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
@@ -301,6 +302,7 @@ enum config_scope {
 	CONFIG_SCOPE_REPO,
 	CONFIG_SCOPE_CMDLINE,
 };
+const char *config_scope_name(enum config_scope scope);
 
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..1e3bc7c8f4 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -37,21 +37,6 @@
  *
  */
 
-static const char *scope_name(enum config_scope scope)
-{
-	switch (scope) {
-	case CONFIG_SCOPE_SYSTEM:
-		return "system";
-	case CONFIG_SCOPE_GLOBAL:
-		return "global";
-	case CONFIG_SCOPE_REPO:
-		return "repo";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
-	default:
-		return "unknown";
-	}
-}
 static int iterate_cb(const char *var, const char *value, void *data)
 {
 	static int nr;
@@ -63,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
 	printf("value=%s\n", value ? value : "(null)");
 	printf("origin=%s\n", current_config_origin_type());
 	printf("name=%s\n", current_config_name());
-	printf("scope=%s\n", scope_name(current_config_scope()));
+	printf("scope=%s\n", config_scope_name(current_config_scope()));
 
 	return 0;
 }
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7b4e1a63eb..5f3e71a160 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=cmdline
+	scope=command line
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 05/10] config: split repo scope to local and worktree
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (3 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 04/10] config: make scope_name non-static and rename it Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:07               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 06/10] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
                               ` (4 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases, but future functionality may care whether or not the config
options come from a worktree or from the repository's actual local
config file.  For example, the planned feature to add a '--show-scope'
to config to allow a user to see which scope listed config options come
from would confuse users if it just printed 'repo' rather than 'local'
or 'worktree' as the documentation would lead them to expect.  As well
as the additional benefit of making the implementation look more like
how the documentation describes the interface.

To accomplish this we split out what was previously considered repo
scope to be local and worktree.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 config.c              | 13 ++++++-------
 config.h              |  3 ++-
 remote.c              |  3 ++-
 t/t1308-config-set.sh |  2 +-
 upload-pack.c         |  3 ++-
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/config.c b/config.c
index 83bb98d65e..7422bdebb1 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
@@ -3304,8 +3301,10 @@ const char *config_scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
-		return "repo";
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "command line";
 	default:
diff --git a/config.h b/config.h
index dcb8c274d4..d3ed41ef8e 100644
--- a/config.h
+++ b/config.h
@@ -299,7 +299,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 const char *config_scope_name(enum config_scope scope);
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 5f3e71a160..728a2b87ce 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-repo
 	origin=file
 	name=.git/config
-	scope=repo
+	scope=local
 
 	key=foo.bar
 	value=from-cmdline
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 06/10] config: clarify meaning of command line scoping
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (4 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 05/10] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:10               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 07/10] config: preserve scope in do_git_config_sequence Matthew Rogers via GitGitGadget
                               ` (3 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  Options passed in using this
mechanism share similar scoping characteristics with the --file and
--blob options of the 'config' command, namely that they are only in use
for that single invocation of git, and that they supersede the normal
system/global/local hierarchy.  This patch introduces
CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
CONFIG_SCOPE_CMDLINE redundant.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 config.c              | 6 +++---
 config.h              | 2 +-
 t/t1308-config-set.sh | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/config.c b/config.c
index 7422bdebb1..fe1e44a43a 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
@@ -3305,8 +3305,8 @@ const char *config_scope_name(enum config_scope scope)
 		return "local";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "command line";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
diff --git a/config.h b/config.h
index d3ed41ef8e..b570f4ce43 100644
--- a/config.h
+++ b/config.h
@@ -301,7 +301,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 const char *config_scope_name(enum config_scope scope);
 
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 728a2b87ce..fba0abe429 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=command line
+	scope=command
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 07/10] config: preserve scope in do_git_config_sequence
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (5 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 06/10] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:11               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 08/10] config: teach git_config_source to remember its scope Matthew Rogers via GitGitGadget
                               ` (2 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

do_git_config_sequence operated under the assumption that it was correct
to set current_parsing_scope to CONFIG_SCOPE_UNKNOWN as part of the
cleanup it does after it finishes execution.  This is incorrect, as it
blows away the current_parsing_scope if do_git_config_sequence is called
recursively.  As such situations are rare (git config running with the
'--blob' option is one example) this has yet to cause a problem, but the
upcoming '--show-scope' option will experience issues in that case, lets
teach do_git_config_sequence to preserve the current_parsing_scope from
before it started execution.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index fe1e44a43a..0e2c693e78 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 08/10] config: teach git_config_source to remember its scope
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (6 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 07/10] config: preserve scope in do_git_config_sequence Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:14               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 09/10] submodule-config: add subomdule config scope Matthew Rogers via GitGitGadget
  2020-02-10  0:30             ` [PATCH v7 10/10] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

There are many situations where the scope of a config command is known
beforehand, such as passing of '--local', '--file', etc. to an
invocation of git config.  However, this information is lost when moving
from builtin/config.c to /config.c.  This historically hasn't been a big
deal, but to prepare for the upcoming --show-scope option we teach
git_config_source to keep track of the source and the config machinery
to use that information to set current_parsing_scope appropriately.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 16 +++++++++++++---
 config.c         |  3 +++
 config.h         | 20 ++++++++++----------
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..0a9778b714 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -622,6 +622,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +638,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +649,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +667,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index 0e2c693e78..9b6afca210 100644
--- a/config.c
+++ b/config.c
@@ -1763,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
diff --git a/config.h b/config.h
index b570f4ce43..165cacb7da 100644
--- a/config.h
+++ b/config.h
@@ -35,11 +35,21 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+};
+const char *config_scope_name(enum config_scope scope);
 
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -295,16 +305,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-const char *config_scope_name(enum config_scope scope);
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 09/10] submodule-config: add subomdule config scope
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (7 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 08/10] config: teach git_config_source to remember its scope Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  2020-02-10 18:15               ` Junio C Hamano
  2020-02-10  0:30             ` [PATCH v7 10/10] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
  9 siblings, 1 reply; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

Before the changes to teach git_config_source to remember scope
information submodule-config.c never needed to consider the question of
config scope.  Even though zeroing out git_config_source is still
correct and preserved the previous behavior of setting the scope to
CONFIG_SCOPE_UNKNOWN, it's better to be explicit about such situations
by explicitly setting the scope.  As none of the current config_scope
enumerations make sense we create CONFIG_SCOPE_SUBMODULE to describe the
situation.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c           | 2 ++
 config.h           | 1 +
 submodule-config.c | 4 +++-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index 9b6afca210..18a6bdd9ff 100644
--- a/config.c
+++ b/config.c
@@ -3311,6 +3311,8 @@ const char *config_scope_name(enum config_scope scope)
 		return "worktree";
 	case CONFIG_SCOPE_COMMAND:
 		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
 	default:
 		return "unknown";
 	}
diff --git a/config.h b/config.h
index 165cacb7da..fe0addb0dc 100644
--- a/config.h
+++ b/config.h
@@ -42,6 +42,7 @@ enum config_scope {
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
 };
 const char *config_scope_name(enum config_scope scope);
 
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
-- 
gitgitgadget


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH v7 10/10] config: add '--show-scope' to print the scope of a config value
  2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
                               ` (8 preceding siblings ...)
  2020-02-10  0:30             ` [PATCH v7 09/10] submodule-config: add subomdule config scope Matthew Rogers via GitGitGadget
@ 2020-02-10  0:30             ` Matthew Rogers via GitGitGadget
  9 siblings, 0 replies; 98+ messages in thread
From: Matthew Rogers via GitGitGadget @ 2020-02-10  0:30 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++---
 builtin/config.c             | 20 ++++++++++--
 t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 7 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..7573160f21 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'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
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 0a9778b714..ee4aef6a35 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static void show_config_scope(struct strbuf *buf)
+{
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = config_scope_name(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +227,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index e5fb9114f6..5464c46c18 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+	global	user.global=true
+	global	user.override=global
+	global	include.path=$INCLUDE_DIR/absolute.include
+	global	user.absolute=include
+	local	user.local=true
+	local	user.override=local
+	local	include.path=../include/relative.include
+	local	user.relative=include
+	command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+	command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+	local	user.local=true
+	local	user.override=local
+	local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope getting a single value' '
+	cat >expect <<-\EOF &&
+	local	true
+	EOF
+	git config --show-scope --get user.local >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+	global	file:$HOME/.gitconfig	user.global=true
+	global	file:$HOME/.gitconfig	user.override=global
+	global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+	global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+	local	file:.git/config	user.local=true
+	local	file:.git/config	user.override=local
+	local	file:.git/config	include.path=../include/relative.include
+	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 &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-10  0:30             ` [PATCH v7 04/10] config: make scope_name non-static and rename it Matthew Rogers via GitGitGadget
@ 2020-02-10 18:02               ` Junio C Hamano
  2020-02-10 21:25                 ` Junio C Hamano
  2020-02-11  0:30                 ` Matt Rogers
  0 siblings, 2 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:02 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> To prepare for the upcoming --show-scope option, we require the ability
> to convert a config_scope enum to a string.  As this was originally
> implemented as a static function 'scope_name()' in
> t/helper/test-config.c, we expose it via config.h and give it a less
> ambiguous name 'config_scope_name()'


> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  config.c               | 16 ++++++++++++++++
>  config.h               |  2 ++
>  t/helper/test-config.c | 17 +----------------
>  t/t1308-config-set.sh  |  2 +-
>  4 files changed, 20 insertions(+), 17 deletions(-)
>
> diff --git a/config.c b/config.c
> index d75f88ca0c..83bb98d65e 100644
> --- a/config.c
> +++ b/config.c
> @@ -3297,6 +3297,22 @@ const char *current_config_origin_type(void)
>  	}
>  }
>  
> +const char *config_scope_name(enum config_scope scope)
> +{
> +	switch (scope) {
> +	case CONFIG_SCOPE_SYSTEM:
> +		return "system";
> +	case CONFIG_SCOPE_GLOBAL:
> +		return "global";
> +	case CONFIG_SCOPE_REPO:
> +		return "repo";
> +	case CONFIG_SCOPE_CMDLINE:
> +		return "command line";

The change from "cmdline" to "command line" does need to happen
before the end of the series, but I do not think it should happen
here, especialy given that the proposed log message explains that
this step is to expose scope_name() under a better name (which is a
very good split point).

How are you reviewing the patches in your own series before sending
them out?  This round is better than the previous rounds where we
didn't have a matching change to the tests so "make test" may not
have passed in the middle of the series, though...

> +	default:
> +		return "unknown";
> +	}
> +}
> +
>  const char *current_config_name(void)
>  {
>  	const char *name;
> diff --git a/config.h b/config.h
> index 91fd4c5e96..dcb8c274d4 100644
> --- a/config.h
> +++ b/config.h
> @@ -35,6 +35,7 @@ struct object_id;
>  
>  #define CONFIG_REGEX_NONE ((void *)1)
>  
> +
>  struct git_config_source {
>  	unsigned int use_stdin:1;
>  	const char *file;
> @@ -301,6 +302,7 @@ enum config_scope {
>  	CONFIG_SCOPE_REPO,
>  	CONFIG_SCOPE_CMDLINE,
>  };
> +const char *config_scope_name(enum config_scope scope);
>  
>  enum config_scope current_config_scope(void);
>  const char *current_config_origin_type(void);
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 214003d5b2..1e3bc7c8f4 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -37,21 +37,6 @@
>   *
>   */
>  
> -static const char *scope_name(enum config_scope scope)
> -{
> -	switch (scope) {
> -	case CONFIG_SCOPE_SYSTEM:
> -		return "system";
> -	case CONFIG_SCOPE_GLOBAL:
> -		return "global";
> -	case CONFIG_SCOPE_REPO:
> -		return "repo";
> -	case CONFIG_SCOPE_CMDLINE:
> -		return "cmdline";
> -	default:
> -		return "unknown";
> -	}
> -}
>  static int iterate_cb(const char *var, const char *value, void *data)
>  {
>  	static int nr;
> @@ -63,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)
>  	printf("value=%s\n", value ? value : "(null)");
>  	printf("origin=%s\n", current_config_origin_type());
>  	printf("name=%s\n", current_config_name());
> -	printf("scope=%s\n", scope_name(current_config_scope()));
> +	printf("scope=%s\n", config_scope_name(current_config_scope()));
>  
>  	return 0;
>  }
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 7b4e1a63eb..5f3e71a160 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-cmdline
>  	origin=command line
>  	name=
> -	scope=cmdline
> +	scope=command line
>  	EOF
>  	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
>  	test_cmp expect actual

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 05/10] config: split repo scope to local and worktree
  2020-02-10  0:30             ` [PATCH v7 05/10] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
@ 2020-02-10 18:07               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:07 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Previously when iterating through git config variables, worktree config
> and local config were both considered "CONFIG_SCOPE_REPO".  This was
> never a problem before as no one had needed to differentiate between the
> two cases, but future functionality may care whether or not the config
> options come from a worktree or from the repository's actual local
> config file.  For example, the planned feature to add a '--show-scope'
> to config to allow a user to see which scope listed config options come
> from would confuse users if it just printed 'repo' rather than 'local'
> or 'worktree' as the documentation would lead them to expect.  As well
> as the additional benefit of making the implementation look more like
> how the documentation describes the interface.
>
> To accomplish this we split out what was previously considered repo
> scope to be local and worktree.
>
> The clients of 'current_config_scope()' who cared about
> CONFIG_SCOPE_REPO are also modified to similarly care about
> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  config.c              | 13 ++++++-------
>  config.h              |  3 ++-
>  remote.c              |  3 ++-
>  t/t1308-config-set.sh |  2 +-
>  upload-pack.c         |  3 ++-
>  5 files changed, 13 insertions(+), 11 deletions(-)

Makes sense.  And this step does exactly what it claims to do and
nothing else, which is very good ;-)  

> diff --git a/config.c b/config.c
> index 83bb98d65e..7422bdebb1 100644
> --- a/config.c
> +++ b/config.c
> @@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
>  		ret += git_config_from_file(fn, user_config, data);
>  
> -	current_parsing_scope = CONFIG_SCOPE_REPO;
> +	current_parsing_scope = CONFIG_SCOPE_LOCAL;
>  	if (!opts->ignore_repo && repo_config &&
>  	    !access_or_die(repo_config, R_OK, 0))
>  		ret += git_config_from_file(fn, repo_config, data);
>  
> -	/*
> -	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
> -	 * But let's not complicate things before it's actually needed.
> -	 */
> +	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
>  	if (!opts->ignore_worktree && repository_format_worktree_config) {
>  		char *path = git_pathdup("config.worktree");
>  		if (!access_or_die(path, R_OK, 0))
> @@ -3304,8 +3301,10 @@ const char *config_scope_name(enum config_scope scope)
>  		return "system";
>  	case CONFIG_SCOPE_GLOBAL:
>  		return "global";
> -	case CONFIG_SCOPE_REPO:
> -		return "repo";
> +	case CONFIG_SCOPE_LOCAL:
> +		return "local";
> +	case CONFIG_SCOPE_WORKTREE:
> +		return "worktree";
>  	case CONFIG_SCOPE_CMDLINE:
>  		return "command line";
>  	default:
> diff --git a/config.h b/config.h
> index dcb8c274d4..d3ed41ef8e 100644
> --- a/config.h
> +++ b/config.h
> @@ -299,7 +299,8 @@ enum config_scope {
>  	CONFIG_SCOPE_UNKNOWN = 0,
>  	CONFIG_SCOPE_SYSTEM,
>  	CONFIG_SCOPE_GLOBAL,
> -	CONFIG_SCOPE_REPO,
> +	CONFIG_SCOPE_LOCAL,
> +	CONFIG_SCOPE_WORKTREE,
>  	CONFIG_SCOPE_CMDLINE,
>  };
>  const char *config_scope_name(enum config_scope scope);
> diff --git a/remote.c b/remote.c
> index 5c4666b53a..593ce297ed 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
>  	}
>  	remote = make_remote(name, namelen);
>  	remote->origin = REMOTE_CONFIG;
> -	if (current_config_scope() == CONFIG_SCOPE_REPO)
> +	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
> +	current_config_scope() == CONFIG_SCOPE_WORKTREE)
>  		remote->configured_in_repo = 1;
>  	if (!strcmp(subkey, "mirror"))
>  		remote->mirror = git_config_bool(key, value);
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 5f3e71a160..728a2b87ce 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-repo
>  	origin=file
>  	name=.git/config
> -	scope=repo
> +	scope=local
>  
>  	key=foo.bar
>  	value=from-cmdline
> diff --git a/upload-pack.c b/upload-pack.c
> index a00d7ece6b..c53249cac1 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
>  		precomposed_unicode = git_config_bool(var, value);
>  	}
>  
> -	if (current_config_scope() != CONFIG_SCOPE_REPO) {
> +	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
> +	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
>  		if (!strcmp("uploadpack.packobjectshook", var))
>  			return git_config_string(&pack_objects_hook, var, value);
>  	}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 06/10] config: clarify meaning of command line scoping
  2020-02-10  0:30             ` [PATCH v7 06/10] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
@ 2020-02-10 18:10               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:10 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
> values passed in via the -c option.  Options passed in using this
> mechanism share similar scoping characteristics with the --file and
> --blob options of the 'config' command, namely that they are only in use
> for that single invocation of git, and that they supersede the normal
> system/global/local hierarchy.  This patch introduces
> CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes
> CONFIG_SCOPE_CMDLINE redundant.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  config.c              | 6 +++---
>  config.h              | 2 +-
>  t/t1308-config-set.sh | 2 +-
>  3 files changed, 5 insertions(+), 5 deletions(-)

This makes sense, even though it is halfway undoing what 04/10
unnecessarily did ;-)

I think I can just wiggle minor fixes in to 04/10 and then adjust
this one to get the series into a better shape myself before queuing
them to expedite the process.  Let me finish reading the remainder
of the topic.

Thanks.

> diff --git a/config.c b/config.c
> index 7422bdebb1..fe1e44a43a 100644
> --- a/config.c
> +++ b/config.c
> @@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  		free(path);
>  	}
>  
> -	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
> +	current_parsing_scope = CONFIG_SCOPE_COMMAND;
>  	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
>  		die(_("unable to parse command-line config"));
>  
> @@ -3305,8 +3305,8 @@ const char *config_scope_name(enum config_scope scope)
>  		return "local";
>  	case CONFIG_SCOPE_WORKTREE:
>  		return "worktree";
> -	case CONFIG_SCOPE_CMDLINE:
> -		return "command line";
> +	case CONFIG_SCOPE_COMMAND:
> +		return "command";
>  	default:
>  		return "unknown";
>  	}
> diff --git a/config.h b/config.h
> index d3ed41ef8e..b570f4ce43 100644
> --- a/config.h
> +++ b/config.h
> @@ -301,7 +301,7 @@ enum config_scope {
>  	CONFIG_SCOPE_GLOBAL,
>  	CONFIG_SCOPE_LOCAL,
>  	CONFIG_SCOPE_WORKTREE,
> -	CONFIG_SCOPE_CMDLINE,
> +	CONFIG_SCOPE_COMMAND,
>  };
>  const char *config_scope_name(enum config_scope scope);
>  
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> index 728a2b87ce..fba0abe429 100755
> --- a/t/t1308-config-set.sh
> +++ b/t/t1308-config-set.sh
> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
>  	value=from-cmdline
>  	origin=command line
>  	name=
> -	scope=command line
> +	scope=command
>  	EOF
>  	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
>  	test_cmp expect actual

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 07/10] config: preserve scope in do_git_config_sequence
  2020-02-10  0:30             ` [PATCH v7 07/10] config: preserve scope in do_git_config_sequence Matthew Rogers via GitGitGadget
@ 2020-02-10 18:11               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:11 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> do_git_config_sequence operated under the assumption that it was correct
> to set current_parsing_scope to CONFIG_SCOPE_UNKNOWN as part of the
> cleanup it does after it finishes execution.  This is incorrect, as it
> blows away the current_parsing_scope if do_git_config_sequence is called
> recursively.  As such situations are rare (git config running with the
> '--blob' option is one example) this has yet to cause a problem, but the
> upcoming '--show-scope' option will experience issues in that case, lets
> teach do_git_config_sequence to preserve the current_parsing_scope from
> before it started execution.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  config.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

This step is new and it does make sense.

Thanks.



> diff --git a/config.c b/config.c
> index fe1e44a43a..0e2c693e78 100644
> --- a/config.c
> +++ b/config.c
> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	char *xdg_config = xdg_config_home("config");
>  	char *user_config = expand_user_path("~/.gitconfig", 0);
>  	char *repo_config;
> +	enum config_scope prev_parsing_scope = current_parsing_scope;
>  
>  	if (opts->commondir)
>  		repo_config = mkpathdup("%s/config", opts->commondir);
> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
>  	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
>  		die(_("unable to parse command-line config"));
>  
> -	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
> +	current_parsing_scope = prev_parsing_scope;
>  	free(xdg_config);
>  	free(user_config);
>  	free(repo_config);

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 08/10] config: teach git_config_source to remember its scope
  2020-02-10  0:30             ` [PATCH v7 08/10] config: teach git_config_source to remember its scope Matthew Rogers via GitGitGadget
@ 2020-02-10 18:14               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:14 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> There are many situations where the scope of a config command is known
> beforehand, such as passing of '--local', '--file', etc. to an
> invocation of git config.  However, this information is lost when moving
> from builtin/config.c to /config.c.  This historically hasn't been a big
> deal, but to prepare for the upcoming --show-scope option we teach
> git_config_source to keep track of the source and the config machinery
> to use that information to set current_parsing_scope appropriately.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---
>  builtin/config.c | 16 +++++++++++++---
>  config.c         |  3 +++
>  config.h         | 20 ++++++++++----------
>  3 files changed, 26 insertions(+), 13 deletions(-)

This is split from the last step in the previous round, and the
splitting makes sense.

Thanks.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 09/10] submodule-config: add subomdule config scope
  2020-02-10  0:30             ` [PATCH v7 09/10] submodule-config: add subomdule config scope Matthew Rogers via GitGitGadget
@ 2020-02-10 18:15               ` Junio C Hamano
  0 siblings, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 18:15 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

"Matthew Rogers via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Matthew Rogers <mattr94@gmail.com>
>
> Before the changes to teach git_config_source to remember scope
> information submodule-config.c never needed to consider the question of
> config scope.  Even though zeroing out git_config_source is still
> correct and preserved the previous behavior of setting the scope to
> CONFIG_SCOPE_UNKNOWN, it's better to be explicit about such situations
> by explicitly setting the scope.  As none of the current config_scope
> enumerations make sense we create CONFIG_SCOPE_SUBMODULE to describe the
> situation.
>
> Signed-off-by: Matthew Rogers <mattr94@gmail.com>
> ---

Other than a typo on the title, I think this one is perfect ;-)

Will queue.

>  config.c           | 2 ++
>  config.h           | 1 +
>  submodule-config.c | 4 +++-
>  3 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/config.c b/config.c
> index 9b6afca210..18a6bdd9ff 100644
> --- a/config.c
> +++ b/config.c
> @@ -3311,6 +3311,8 @@ const char *config_scope_name(enum config_scope scope)
>  		return "worktree";
>  	case CONFIG_SCOPE_COMMAND:
>  		return "command";
> +	case CONFIG_SCOPE_SUBMODULE:
> +		return "submodule";
>  	default:
>  		return "unknown";
>  	}
> diff --git a/config.h b/config.h
> index 165cacb7da..fe0addb0dc 100644
> --- a/config.h
> +++ b/config.h
> @@ -42,6 +42,7 @@ enum config_scope {
>  	CONFIG_SCOPE_LOCAL,
>  	CONFIG_SCOPE_WORKTREE,
>  	CONFIG_SCOPE_COMMAND,
> +	CONFIG_SCOPE_SUBMODULE,
>  };
>  const char *config_scope_name(enum config_scope scope);
>  
> diff --git a/submodule-config.c b/submodule-config.c
> index 85064810b2..b8e97d8ae8 100644
> --- a/submodule-config.c
> +++ b/submodule-config.c
> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
>  static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
>  {
>  	if (repo->worktree) {
> -		struct git_config_source config_source = { 0 };
> +		struct git_config_source config_source = {
> +			0, .scope = CONFIG_SCOPE_SUBMODULE
> +		};
>  		const struct config_options opts = { 0 };
>  		struct object_id oid;
>  		char *file;

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-10 18:02               ` Junio C Hamano
@ 2020-02-10 21:25                 ` Junio C Hamano
  2020-02-11  0:30                 ` Matt Rogers
  1 sibling, 0 replies; 98+ messages in thread
From: Junio C Hamano @ 2020-02-10 21:25 UTC (permalink / raw)
  To: Matthew Rogers via GitGitGadget; +Cc: git, Matthew Rogers

Junio C Hamano <gitster@pobox.com> writes:

> The change from "cmdline" to "command line" does need to happen
> before the end of the series, but I do not think it should happen
> here, especialy given that the proposed log message explains that
> this step is to expose scope_name() under a better name (which is a
> very good split point).

I'll tweak this step with the attached patch, and then adjust
06/10 as needed, while queuing.

 config.c              | 2 +-
 config.h              | 1 -
 t/t1308-config-set.sh | 2 +-
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index 83bb98d65e..a922b136e5 100644
--- a/config.c
+++ b/config.c
@@ -3307,7 +3307,7 @@ const char *config_scope_name(enum config_scope scope)
 	case CONFIG_SCOPE_REPO:
 		return "repo";
 	case CONFIG_SCOPE_CMDLINE:
-		return "command line";
+		return "cmdline";
 	default:
 		return "unknown";
 	}
diff --git a/config.h b/config.h
index dcb8c274d4..c063f33ff6 100644
--- a/config.h
+++ b/config.h
@@ -35,7 +35,6 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
-
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 5f3e71a160..7b4e1a63eb 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '
 	value=from-cmdline
 	origin=command line
 	name=
-	scope=command line
+	scope=cmdline
 	EOF
 	GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
 	test_cmp expect actual

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-10 18:02               ` Junio C Hamano
  2020-02-10 21:25                 ` Junio C Hamano
@ 2020-02-11  0:30                 ` Matt Rogers
  2020-02-11  1:58                   ` Emily Shaffer
  2020-02-11  6:10                   ` Junio C Hamano
  1 sibling, 2 replies; 98+ messages in thread
From: Matt Rogers @ 2020-02-11  0:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, Git Mailing List

>
> How are you reviewing the patches in your own series before sending
> them out?  This round is better than the previous rounds where we
> didn't have a matching change to the tests so "make test" may not
> have passed in the middle of the series, though...
>

I went through each patch individually using rebase -i and built/tested it.
Although just to save time I only did t1300 and t1308 since I believe those were
the only ones that should be affected.  I can write a script that
would run the whole
test suite overnight for me and make sure the series shakes out okay,
if you'd like.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-11  0:30                 ` Matt Rogers
@ 2020-02-11  1:58                   ` Emily Shaffer
  2020-02-11  6:10                   ` Junio C Hamano
  1 sibling, 0 replies; 98+ messages in thread
From: Emily Shaffer @ 2020-02-11  1:58 UTC (permalink / raw)
  To: Matt Rogers
  Cc: Junio C Hamano, Matthew Rogers via GitGitGadget, Git Mailing List

On Mon, Feb 10, 2020 at 07:30:22PM -0500, Matt Rogers wrote:
> >
> > How are you reviewing the patches in your own series before sending
> > them out?  This round is better than the previous rounds where we
> > didn't have a matching change to the tests so "make test" may not
> > have passed in the middle of the series, though...
> >
> 
> I went through each patch individually using rebase -i and built/tested it.
> Although just to save time I only did t1300 and t1308 since I believe those were
> the only ones that should be affected.  I can write a script that
> would run the whole
> test suite overnight for me and make sure the series shakes out okay,
> if you'd like.

Not sure whether you intend to do this or not, but to maybe save you
some scripting, I do this like so:

  git rebase -x \
    "make -j16 && (cd t && prove -j16 -v --shuffle t[0-9]*.sh)" master

If the tests fail, the rebase is paused, which can be understandably
disappointing if you walk away from it overnight only to have it fail
after 10 minutes, though. :)

 - Emily

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-11  0:30                 ` Matt Rogers
  2020-02-11  1:58                   ` Emily Shaffer
@ 2020-02-11  6:10                   ` Junio C Hamano
  2020-02-11 12:37                     ` Matt Rogers
  1 sibling, 1 reply; 98+ messages in thread
From: Junio C Hamano @ 2020-02-11  6:10 UTC (permalink / raw)
  To: Matt Rogers; +Cc: Matthew Rogers via GitGitGadget, Git Mailing List

Matt Rogers <mattr94@gmail.com> writes:

>> How are you reviewing the patches in your own series before sending
>> them out?  This round is better than the previous rounds where we
>> didn't have a matching change to the tests so "make test" may not
>> have passed in the middle of the series, though...
>>
>
> I went through each patch individually using rebase -i and built/tested it.
> Although just to save time I only did t1300 and t1308 since I believe those were
> the only ones that should be affected.  I can write a script that
> would run the whole
> test suite overnight for me and make sure the series shakes out okay,
> if you'd like.

What I like does not matter.  

What I pointed out for 04/10 wouldn't have been caught by your
testing anyway, as both the code and the test had matching
unnecessry changes.  I was wondering if you are relying too heavily
on just tests and without actually proofreading the changes to see
if they still make sense in the context of the updated series, and
if my suspicion was correct, if there are something reviewers can do
to help the authors.



^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH v7 04/10] config: make scope_name non-static and rename it
  2020-02-11  6:10                   ` Junio C Hamano
@ 2020-02-11 12:37                     ` Matt Rogers
  0 siblings, 0 replies; 98+ messages in thread
From: Matt Rogers @ 2020-02-11 12:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matthew Rogers via GitGitGadget, Git Mailing List

On Tue, Feb 11, 2020 at 1:10 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Matt Rogers <mattr94@gmail.com> writes:
>
> >> How are you reviewing the patches in your own series before sending
> >> them out?  This round is better than the previous rounds where we
> >> didn't have a matching change to the tests so "make test" may not
> >> have passed in the middle of the series, though...
> >>
> >
> > I went through each patch individually using rebase -i and built/tested it.
> > Although just to save time I only did t1300 and t1308 since I believe those were
> > the only ones that should be affected.  I can write a script that
> > would run the whole
> > test suite overnight for me and make sure the series shakes out okay,
> > if you'd like.
>
> What I like does not matter.
>
> What I pointed out for 04/10 wouldn't have been caught by your
> testing anyway, as both the code and the test had matching
> unnecessry changes.  I was wondering if you are relying too heavily
> on just tests and without actually proofreading the changes to see
> if they still make sense in the context of the updated series, and
> if my suspicion was correct, if there are something reviewers can do
> to help the authors.
>
>

I do try to proofread patches, I'm just not the most careful of reviewers at
times, partially as a personal problem and partially as this is a new workflow
for me.  As for the particular issue, I just thought it was a good idea at the
time and I didn't think it all the way through


-- 
Matthew Rogers

^ permalink raw reply	[flat|nested] 98+ messages in thread

end of thread, back to index

Thread overview: 98+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18  1:11 [PATCH 0/1] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
2019-12-18  1:11 ` [PATCH 1/1] " Matthew Rogers via GitGitGadget
2019-12-18 19:46   ` Junio C Hamano
2019-12-19  5:05     ` Jeff King
2019-12-19 17:51       ` Junio C Hamano
2019-12-18 22:45   ` Philip Oakley
2019-12-19  0:12     ` mattr94
2019-12-19 17:56       ` Junio C Hamano
2019-12-20 22:58         ` Matt Rogers
2019-12-21  2:37           ` Junio C Hamano
2019-12-21  3:08             ` Matt Rogers
2019-12-21 23:47               ` Junio C Hamano
2020-01-09 10:16 ` [PATCH v2 0/4] " Matthew Rogers via GitGitGadget
2020-01-09 10:16   ` [PATCH v2 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-01-09 19:07     ` Junio C Hamano
2020-01-09 23:22       ` Matt Rogers
2020-01-10 11:55     ` Jeff King
2020-01-09 10:16   ` [PATCH v2 2/4] config: fix config scope enum Matthew Rogers via GitGitGadget
2020-01-09 19:06     ` Junio C Hamano
2020-01-09 23:29       ` Matt Rogers
2020-01-09 10:16   ` [PATCH v2 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-01-09 19:13     ` Junio C Hamano
2020-01-09 23:41       ` Matt Rogers
2020-01-09 10:16   ` [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
2020-01-09 19:50     ` Junio C Hamano
2020-01-09 23:47       ` Matt Rogers
2020-01-17 15:31   ` [PATCH v3 0/4] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
2020-01-17 15:31     ` [PATCH v3 1/4] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-01-17 15:31     ` [PATCH v3 2/4] config: refine config scope enum Matthew Rogers via GitGitGadget
2020-01-17 20:44       ` Junio C Hamano
2020-01-18 15:27         ` Matt Rogers
2020-01-18 18:09           ` Junio C Hamano
2020-01-17 15:31     ` [PATCH v3 3/4] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-01-17 21:00       ` Junio C Hamano
2020-01-18 15:33         ` Matt Rogers
2020-01-17 15:31     ` [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
2020-01-17 21:21       ` Junio C Hamano
2020-01-17 21:26         ` Bert Wesarg
2020-01-18 15:42         ` Matt Rogers
2020-01-24  0:21     ` [PATCH v4 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
2020-01-24  0:21       ` [PATCH v4 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-01-24  0:21       ` [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
2020-01-24 18:43         ` Junio C Hamano
2020-01-24  0:21       ` [PATCH v4 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
2020-01-24 18:45         ` Junio C Hamano
2020-01-24  0:21       ` [PATCH v4 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
2020-01-24 18:49         ` Junio C Hamano
2020-01-24 19:09         ` Junio C Hamano
2020-01-24  0:21       ` [PATCH v4 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-01-24  0:21       ` [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
2020-01-24 19:18         ` Junio C Hamano
2020-01-24 20:22         ` Junio C Hamano
2020-01-24 20:49           ` Matt Rogers
2020-01-25  0:10             ` Junio C Hamano
2020-01-24 19:22       ` [PATCH v4 0/6] config: allow user to know scope of config options Junio C Hamano
2020-01-25  0:39       ` [PATCH v5 " Matthew Rogers via GitGitGadget
2020-01-25  0:39         ` [PATCH v5 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-01-25  0:39         ` [PATCH v5 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
2020-01-25  0:39         ` [PATCH v5 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
2020-01-25  0:39         ` [PATCH v5 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
2020-01-27 23:09           ` Junio C Hamano
2020-01-25  0:39         ` [PATCH v5 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-01-25  0:39         ` [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
2020-01-27 23:12           ` Junio C Hamano
2020-01-28  1:31             ` Matt Rogers
2020-01-29  3:34         ` [PATCH v6 0/6] config: allow user to know scope of config options Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 1/6] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 2/6] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 3/6] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 4/6] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 5/6] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-01-29  3:34           ` [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget
2020-01-29  9:08             ` Bert Wesarg
2020-01-29 23:03               ` Matt Rogers
2020-02-05 19:01                 ` Junio C Hamano
2020-01-29  5:29           ` [PATCH v6 0/6] config: allow user to know scope of config options Junio C Hamano
2020-02-10  0:30           ` [PATCH v7 00/10] " Matthew Rogers via GitGitGadget
2020-02-10  0:30             ` [PATCH v7 01/10] config: fix typo in variable name Matthew Rogers via GitGitGadget
2020-02-10  0:30             ` [PATCH v7 02/10] t1300: fix over-indented HERE-DOCs Matthew Rogers via GitGitGadget
2020-02-10  0:30             ` [PATCH v7 03/10] t1300: create custom config file without special characters Matthew Rogers via GitGitGadget
2020-02-10  0:30             ` [PATCH v7 04/10] config: make scope_name non-static and rename it Matthew Rogers via GitGitGadget
2020-02-10 18:02               ` Junio C Hamano
2020-02-10 21:25                 ` Junio C Hamano
2020-02-11  0:30                 ` Matt Rogers
2020-02-11  1:58                   ` Emily Shaffer
2020-02-11  6:10                   ` Junio C Hamano
2020-02-11 12:37                     ` Matt Rogers
2020-02-10  0:30             ` [PATCH v7 05/10] config: split repo scope to local and worktree Matthew Rogers via GitGitGadget
2020-02-10 18:07               ` Junio C Hamano
2020-02-10  0:30             ` [PATCH v7 06/10] config: clarify meaning of command line scoping Matthew Rogers via GitGitGadget
2020-02-10 18:10               ` Junio C Hamano
2020-02-10  0:30             ` [PATCH v7 07/10] config: preserve scope in do_git_config_sequence Matthew Rogers via GitGitGadget
2020-02-10 18:11               ` Junio C Hamano
2020-02-10  0:30             ` [PATCH v7 08/10] config: teach git_config_source to remember its scope Matthew Rogers via GitGitGadget
2020-02-10 18:14               ` Junio C Hamano
2020-02-10  0:30             ` [PATCH v7 09/10] submodule-config: add subomdule config scope Matthew Rogers via GitGitGadget
2020-02-10 18:15               ` Junio C Hamano
2020-02-10  0:30             ` [PATCH v7 10/10] config: add '--show-scope' to print the scope of a config value Matthew Rogers via GitGitGadget

git@vger.kernel.org list mirror (unofficial, one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.io/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git