{"thread":{"id":"52477","subject":"[PATCH 0/1] config: allow user to know scope of config options","startedAt":"2019-12-18T01:11:08Z","lastAt":"2020-02-11T12:37:46Z","messageCount":98,"participants":["Matthew Rogers via GitGitGadget","Junio C Hamano","Philip Oakley","mattr94@gmail.com","Jeff King","Matt Rogers","Bert Wesarg","Emily Shaffer"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"388413","messageId":"pull.478.git.1576631464.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":null,"subject":"[PATCH 0/1] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-12-18T01:11:03Z","receivedAt":"2019-12-18T01:11:08Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nMatthew Rogers (1):\n  config: allow user to know scope of config options\n\n builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------\n t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 103 insertions(+), 8 deletions(-)\n\n\nbase-commit: b02fd2accad4d48078671adf38fe5b5976d77304\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n-- \ngitgitgadget\n"},{"id":"388414","messageId":"ec699bb3e64c74e6e87a20bbb5efac12a13cb077.1576631464.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.git.1576631464.gitgitgadget@gmail.com","subject":"[PATCH 1/1] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2019-12-18T01:11:04Z","receivedAt":"2019-12-18T01:11:11Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nAdd new option --show-scope which allows a user to know what the scope\nof listed config options are (local/global/system/etc.).\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------\n t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 103 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..9a9c2d12f2 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,10 +29,11 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -151,10 +152,11 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (system, global, local, command line)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -178,23 +180,63 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n \tstrbuf_addch(buf, term);\n }\n \n+static const char *scope_to_string(enum config_scope scope) {\n+\t/*\n+\t * --local, --global, and --system work the same as --file so there's\n+\t * no easy way for the parser to tell the difference when it is\n+\t * setting the scope, so we use our information about which options\n+\t * were passed\n+\t */\n+\tif (use_local_config || scope == CONFIG_SCOPE_REPO) {\n+\t\treturn \"local\";\n+\t} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {\n+\t\treturn \"global\";\n+\t} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {\n+\t\treturn \"system\";\n+\t} else if (given_config_source.use_stdin ||\n+\t\tgiven_config_source.blob ||\n+\t\tgiven_config_source.file ||\n+\t\tscope == CONFIG_SCOPE_CMDLINE) {\n+\t\treturn \"command line\";\n+\t} else {\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = scope_to_string(current_config_scope());\n+\n+\tstrbuf_addch(buf, '(');\n+\tif (end_nul)\n+\t\tstrbuf_addstr(buf, N_(scope));\n+\telse\n+\t\tquote_c_style(scope, buf, NULL, 0);\n+\tstrbuf_addch(buf, ')');\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n-\t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n+\t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_nul\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n \t}\n@@ -213,6 +255,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -678,7 +722,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..098f305bdd 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1766,6 +1766,57 @@ test_expect_success !MINGW '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+\n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\t\t(global)\tuser.global=true\n+\t\t(global)\tuser.override=global\n+\t\t(global)\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\t(global)\tuser.absolute=include\n+\t\t(local)\tuser.local=true\n+\t\t(local)\tuser.override=local\n+\t\t(local)\tinclude.path=../include/relative.include\n+\t\t(local)\tuser.relative=include\n+\t\t(command line)\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\t\t(command line)\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\t\t(local)\tuser.local=true\n+\t\t(local)\tuser.override=local\n+\t\t(local)\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\t\t(global)\tfile:$HOME/.gitconfig\tuser.global=true\n+\t\t(global)\tfile:$HOME/.gitconfig\tuser.override=global\n+\t\t(global)\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\t(global)\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\t\t(local)\tfile:.git/config\tuser.local=true\n+\t\t(local)\tfile:.git/config\tuser.override=local\n+\t\t(local)\tfile:.git/config\tinclude.path=../include/relative.include\n+\t\t(local)\tfile:.git/../include/relative.include\tuser.relative=include\n+\t\t(command line)\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"388472","messageId":"xmqqa77pe7sx.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"ec699bb3e64c74e6e87a20bbb5efac12a13cb077.1576631464.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-18T19:46:06Z","receivedAt":"2019-12-18T19:46:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> -static int end_null;\n> +static int end_nul;\n> -\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n> +\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n> -\tconst char term = end_null ? '\\0' : '\\t';\n> +\tconst char term = end_nul ? '\\0' : '\\t';\n> -\tif (end_null)\n> +\tif (end_nul)\n\nThese are correct changes, but is unrelated noise in the context of\nthe theme of the patch, no?\n\n> +static const char *scope_to_string(enum config_scope scope) {\n> +\t/*\n> +\t * --local, --global, and --system work the same as --file so there's\n> +\t * no easy way for the parser to tell the difference when it is\n> +\t * setting the scope, so we use our information about which options\n> +\t * were passed\n> +\t */\n> +\tif (use_local_config || scope == CONFIG_SCOPE_REPO) {\n> +\t\treturn \"local\";\n> +\t} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {\n> +\t\treturn \"global\";\n> +\t} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {\n> +\t\treturn \"system\";\n\nThe above is slightly tricky; --global/--system/--local are made\nmutually exclusive in the higher level, so if any of them is set,\nwe do not even need to look at the \"scope\" to tell what kind of\nsource we are reading from.\n\n> +\t} else if (given_config_source.use_stdin ||\n> +\t\tgiven_config_source.blob ||\n> +\t\tgiven_config_source.file ||\n> +\t\tscope == CONFIG_SCOPE_CMDLINE) {\n> +\t\treturn \"command line\";\n\nI am not sure what the implication of saying \"they came from the\ncommand line\" when we read from the standard input or from a blob.\n\n> +\t} else {\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n\nIn any case, the need for such logic that says \"scope might not say\nit is REPO, but when use_local_config is true, we are doing a local\nconfig\" implies that \"scope\" parameter the caller of this function\nhas is not set correctly when these options are used---would that be\nthe real bug that needs fixing, rather than getting \"worked around\"\nwith a code like this?\n\nIt almost makes me point fingers at config.c::config_with_options()\nwhere config_source is inspected and git_config_from_*() helpers are\ncalled without setting the current_parsing_scope.  Unlike these\ncases, when do_git_config_sequence() is called from that function,\nthe scope is recorded in the variable before each standard config\nsource file is opened and read.  What would we be breaking if we\ntaught the function to set the current_parsing_scope variable\ncorrectly even when reading from the config_source?  That would\ncertainly simplify this function quite a lot, but if the other parts\nof the codebase relies on the current behaviour, we cannot make such\na change lightly.\n\n> +static void show_config_scope(struct strbuf *buf)\n> +{\n> +\tconst char term = end_nul ? '\\0' : '\\t';\n> +\tconst char *scope = scope_to_string(current_config_scope());\n> +\n> +\tstrbuf_addch(buf, '(');\n> +\tif (end_nul)\n> +\t\tstrbuf_addstr(buf, N_(scope));\n> +\telse\n> +\t\tquote_c_style(scope, buf, NULL, 0);\n\nIsn't this overkill?  I think this code was copied-and-pasted from\nthe other function that needs to show an arbitrary end-user supplied\ndata which is a pathname, so it makes perfect sense to use c-style\nquoting, but the token scope_to_string() returns is taken from a\nbounded set that doesn't require such quoting, no?\n\n> +\tstrbuf_addch(buf, ')');\n> +\tstrbuf_addch(buf, term);\n> +}\n> +\n"},{"id":"388485","messageId":"9a91caa0-72c3-3a38-3eb7-55a43537762e@iee.email","threadId":"52477","inReplyTo":"ec699bb3e64c74e6e87a20bbb5efac12a13cb077.1576631464.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.email","sentAt":"2019-12-18T22:45:04Z","receivedAt":"2019-12-18T22:45:06Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"Hi Matthew,\n\nOn 18/12/2019 01:11, Matthew Rogers via GitGitGadget wrote:\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Add new option --show-scope which allows a user to know what the scope\n> of listed config options are (local/global/system/etc.).\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  builtin/config.c  | 60 ++++++++++++++++++++++++++++++++++++++++-------\n>  t/t1300-config.sh | 51 ++++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 103 insertions(+), 8 deletions(-)\n\nDoesn't this also need a man page update as well for adding the option\nto the synopsis.\n\nThe commit message doesn't fully highlight that the config list will\noften be all the users config values, so each value will be\ndisambiguated/identified as to it's origin.\n\nPhilip\n"},{"id":"388489","messageId":"03b001d5b601$09b950e0$1d2bf2a0$@gmail.com","threadId":"52477","inReplyTo":"9a91caa0-72c3-3a38-3eb7-55a43537762e@iee.email","subject":"RE: [PATCH 1/1] config: allow user to know scope of config options","fromName":"","fromEmail":"mattr94@gmail.com","sentAt":"2019-12-19T00:12:44Z","receivedAt":"2019-12-19T00:12:50Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"Junio,\n\n>These are correct changes, but is unrelated noise in the context of\n>the theme of the patch, no?\n\nI think that's the case, would the recommended course of action be to\nmove these changes into its own commit? \n\n\n>> +     if (use_local_config || scope == CONFIG_SCOPE_REPO) {\n>> +             return \"local\";\n>> +     } else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {\n>> +             return \"global\";\n>> +     } else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {\n>> +             return \"system\";\n>\n>The above is slightly tricky; --global/--system/--local are made\n>mutually exclusive in the higher level, so if any of them is set,\n>we do not even need to look at the \"scope\" to tell what kind of\n>source we are reading from.\n\nSo the way I structured these was to mirror the way other parts \nof this file check if we should be doing a --local, etc. and mirrored \nthat here.  This could definitely be cleaned up if we change the behavior\nwith how --local, etc. set the current_config_scope.\n\n\n>> +     } else if (given_config_source.use_stdin ||\n>> +             given_config_source.blob ||\n>> +             given_config_source.file ||\n>> +             scope == CONFIG_SCOPE_CMDLINE) {\n>> +             return \"command line\";\n>\n>I am not sure what the implication of saying \"they came from the\n>command line\" when we read from the standard input or from a blob.\n\nI agree with you here, I only put this as \"command line\" \nbecause they came from a place that was ultimately fed in from \ncommand line options (--file/--blob).  I wouldn't have a problem with \ncalling them out as their own scope (\"file\", \"blob\", \"stdin\").\n\n\n>> +     } else {\n>> +             return \"unknown\";\n>> +     }\n>> +}\n>\n>In any case, the need for such logic that says \"scope might not say\n>it is REPO, but when use_local_config is true, we are doing a local\n>config\" implies that \"scope\" parameter the caller of this function\n>has is not set correctly when these options are used---would that be\n>the real bug that needs fixing, rather than getting \"worked around\"\n>with a code like this?\n>\n>It almost makes me point fingers at config.c::config_with_options()\n>where config_source is inspected and git_config_from_*() helpers are\n>called without setting the current_parsing_scope.  Unlike these\n>cases, when do_git_config_sequence() is called from that function,\n>the scope is recorded in the variable before each standard config\n>source file is opened and read.  What would we be breaking if we\n>taught the function to set the current_parsing_scope variable\n>correctly even when reading from the config_source?  That would\n>certainly simplify this function quite a lot, but if the other parts\n>of the codebase relies on the current behaviour, we cannot make such\n>a change lightly.\n\nFrom what I can tell from a cursory glance. the only two clients of \nthis function are remote.c and upload-pack.c.  The usecase for remote.c\n mostly seems to be to determine the result of `remote_is_configured()`\nwhich (more importantly) seems to be done when that iterates through \nthe relevant configuration options.  Similarly for upload-pack.c.\n\nI don't think it would be harmful for git config --local, etc. to set that\nas we would normally intuit.\n\n\n>> +static void show_config_scope(struct strbuf *buf)\n>> +{\n>> +     const char term = end_nul ? '\\0' : '\\t';\n>> +     const char *scope = scope_to_string(current_config_scope());\n>> +\n>> +     strbuf_addch(buf, '(');\n>> +     if (end_nul)\n>> +             strbuf_addstr(buf, N_(scope));\n>> +     else\n>> +             quote_c_style(scope, buf, NULL, 0);\n>\n>Isn't this overkill?  I think this code was copied-and-pasted from\n>the other function that needs to show an arbitrary end-user supplied\n>data which is a pathname, so it makes perfect sense to use c-style\n>quoting, but the token scope_to_string() returns is taken from a\n>bounded set that doesn't require such quoting, no?\n\nYeah, I guess that is a copy+paste mistake.  I don't think its \nnecessary since we control the input into this function, So I'll fix \nthat.\n\n\nPhilip,\n\n>Doesn't this also need a man page update as well for adding the option\n>to the synopsis.\n>\n>The commit message doesn't fully highlight that the config list will\n>often be all the users config values, so each value will be\n>disambiguated/identified as to it's origin.\n\nI'm agreed on these. So I'll look to readjust that.\n\n"},{"id":"388505","messageId":"20191219050545.GC89333@coredump.intra.peff.net","threadId":"52477","inReplyTo":"xmqqa77pe7sx.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-12-19T05:05:45Z","receivedAt":"2019-12-19T05:05:48Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Dec 18, 2019 at 11:46:06AM -0800, Junio C Hamano wrote:\n\n> It almost makes me point fingers at config.c::config_with_options()\n> where config_source is inspected and git_config_from_*() helpers are\n> called without setting the current_parsing_scope.  Unlike these\n> cases, when do_git_config_sequence() is called from that function,\n> the scope is recorded in the variable before each standard config\n> source file is opened and read.  What would we be breaking if we\n> taught the function to set the current_parsing_scope variable\n> correctly even when reading from the config_source?  That would\n> certainly simplify this function quite a lot, but if the other parts\n> of the codebase relies on the current behaviour, we cannot make such\n> a change lightly.\n\nAs the author of the SCOPE enum, I think this is the right direction.\nThe only users of current_config_scope() are in config callbacks (e.g.,\nupload_pack_config() checks it for the \"packobjectshook\"), which you\ncouldn't trigger via \"git config\" anyway.\n\nThe main reason I didn't set the scope before in config_with_options()\nis that it's not given the scope at all; git-config resolves it to the\nfilename. So if git_config_source grows an enum to select the type, and\nall that filename-resolution gets pushed down into config_with_options(),\nthe whole thing would fall out naturally, I think.\n\n-Peff\n"},{"id":"388530","messageId":"xmqqy2v8b3w7.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"20191219050545.GC89333@coredump.intra.peff.net","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-19T17:51:04Z","receivedAt":"2019-12-19T17:51:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> ... So if git_config_source grows an enum to select the type, and\n> all that filename-resolution gets pushed down into config_with_options(),\n> the whole thing would fall out naturally, I think.\n\nMakes sense.\n"},{"id":"388532","messageId":"xmqqtv5wb3nm.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"03b001d5b601$09b950e0$1d2bf2a0$@gmail.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-19T17:56:13Z","receivedAt":"2019-12-19T17:56:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"<mattr94@gmail.com> writes:\n\n>>These are correct changes, but is unrelated noise in the context of\n>>the theme of the patch, no?\n>\n> I think that's the case, would the recommended course of action be to\n> move these changes into its own commit? \n>\n\nYup, and it generally is a good idea to make such a clean-up patch\neither early in the series, or as a standalone patch (with a note\nunder three-dash lines that another topic is coming on top of the\ncleanup), because it would be much less likely to introduce new bugs\nand can be merged quicly to 'next' and then to 'master' to serve as\na base to build your other changes on top.\n\n"},{"id":"388695","messageId":"CAOjrSZsiW-vxHKBqbEuBS6rpQ7m22wRp0UwGVVAJE2WE3bh-XQ@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqtv5wb3nm.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2019-12-20T22:58:22Z","receivedAt":"2019-12-20T22:58:36Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"Philip,\n\n>The commit message doesn't fully highlight that the config list will\n>often be all the users config values, so each value will be\n>disambiguated/identified as to it's origin.\n\nI don't really understand what you mean by \"it's origin\" here.  When\nyou say origin, do you mean in the \"--show-origin\" sense of \"file/blob/etc.\"\nor something else? Because scope is kind of an orthogonal concept to origin\nin that sense as you can have files with different origins but the same scope.\n\nThanks,\nMatt\n\n\nOn Thu, Dec 19, 2019 at 12:56 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> <mattr94@gmail.com> writes:\n>\n> >>These are correct changes, but is unrelated noise in the context of\n> >>the theme of the patch, no?\n> >\n> > I think that's the case, would the recommended course of action be to\n> > move these changes into its own commit?\n> >\n>\n> Yup, and it generally is a good idea to make such a clean-up patch\n> either early in the series, or as a standalone patch (with a note\n> under three-dash lines that another topic is coming on top of the\n> cleanup), because it would be much less likely to introduce new bugs\n> and can be merged quicly to 'next' and then to 'master' to serve as\n> a base to build your other changes on top.\n>\n\n\n-- \nMatthew Rogers\n"},{"id":"388701","messageId":"xmqqtv5u76ag.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZsiW-vxHKBqbEuBS6rpQ7m22wRp0UwGVVAJE2WE3bh-XQ@mail.gmail.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-21T02:37:27Z","receivedAt":"2019-12-21T02:37:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n> Philip,\n>\n>>The commit message doesn't fully highlight that the config list will\n>>often be all the users config values, so each value will be\n>>disambiguated/identified as to it's origin.\n>\n> I don't really understand what you mean by \"it's origin\" here.  When\n> you say origin, do you mean in the \"--show-origin\" sense of \"file/blob/etc.\"\n> or something else? Because scope is kind of an orthogonal concept to origin\n> in that sense as you can have files with different origins but the same scope.\n\nI do not think origin and scope are orghogonal, though.  Can the\nsame file appear as the source for different configuration var-value\npair in two different scopes?\n\nIt is likely that you can _guess_ with high precision that given a\npathname reported by --show-origin what scope it is in.  It on the\nother hand is not so trivial given a scope to guess which exact file\na var-value pair came from, I would think.\\\n"},{"id":"388702","messageId":"CAOjrSZvkT3TZwEvvnhRBVcuivhy46n8p9sV+3wZdvD=5f_cuRQ@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqtv5u76ag.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2019-12-21T03:08:35Z","receivedAt":"2019-12-21T03:08:56Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"On Fri, Dec 20, 2019 at 9:37 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> I do not think origin and scope are orghogonal, though.  Can the\n> same file appear as the source for different configuration var-value\n> pair in two different scopes?\n\nI meant orthogonal in two senses:\n\nThat given the current implementation you don't need to have both\noptions active at\nthe same time but can have them active at both times.\n\nAnd that origin and scope correlate, but aren't necessarily\none-for-one.  For example, --show-origin lists in a known order, but it follows\nincludes and lists the origin as the included file.  so if you include a file\nglobally which has includeif \"gitdir:...\" directives then it can get hairy when\nall your config files are structured like that.\n\nAlthough, to be fair I doubt that that kind of situation is normal\n\n>\n> It is likely that you can _guess_ with high precision that given a\n> pathname reported by --show-origin what scope it is in.  It on the\n> other hand is not so trivial given a scope to guess which exact file\n> a var-value pair came from, I would think.\\\n\nNormally yes, but things can get complicating depending on your\nconfiguration/include situation.\n"},{"id":"388767","messageId":"xmqqpngh6y1j.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZvkT3TZwEvvnhRBVcuivhy46n8p9sV+3wZdvD=5f_cuRQ@mail.gmail.com","subject":"Re: [PATCH 1/1] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-21T23:47:52Z","receivedAt":"2019-12-21T23:47:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n> And that origin and scope correlate, but aren't necessarily\n> one-for-one.\n\nYes, exactly.  When I see \"orthogonal\", I expect the word describes\nthings that do not correlate.\n\nI can see values in the option that gives scope but not path in\norder to write scripts that limits var-value pairs to be used\n(e.g. \"I do not want to be affected by the per-repository values\",\n\"I do not trust settings that comes system-wide\").  I also can see\nvalues in the option that gives only path when debugging the\nconfiguration file.\n\nI briefly wondered, for the purpose of such \"I do want to see only\nthose settings coming from these scopes\" script, it may make more\nsense to have the command _filter_ the var-value pairs, instead of\nshowing all of them with label, but that feature always exists ;-)\n"},{"id":"389525","messageId":"b40480f03a5643761bd06d4b9c495a99b98a1ac8.1578565001.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","subject":"[PATCH v2 1/4] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-09T10:16:38Z","receivedAt":"2020-01-09T10:16:47Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"389526","messageId":"e8e05f39407365a1bf5008820267d362e0cbffd6.1578565001.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","subject":"[PATCH v2 2/4] config: fix config scope enum","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-09T10:16:39Z","receivedAt":"2020-01-09T10:16:48Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases.\n\nAdditionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL\nto reflect its new, more specific meaning.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 7 ++-----\n config.h               | 3 ++-\n remote.c               | 3 ++-\n t/helper/test-config.c | 4 +++-\n upload-pack.c          | 3 ++-\n 5 files changed, 11 insertions(+), 9 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..447a013a15 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..284d92fb0e 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,7 +298,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n \ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..6695e463eb 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n+\tcase CONFIG_SCOPE_LOCAL:\n \t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"cmdline\";\n \tdefault:\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"389527","messageId":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.git.1576631464.gitgitgadget@gmail.com","subject":"[PATCH v2 0/4] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-09T10:16:37Z","receivedAt":"2020-01-09T10:16:50Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v1:\n\n * Cleaned up meaning of scoping, specifically separating \"repo\" into\n   \"local\" and \"worktree\" as well as expanding \"cmdline\" into \"command\"\n   scoping, added submodule scoping\n * Taught struct git_config_source to remember the scope of the command that\n   is filling it out\n * do_git_config_sequence() now remembers the previous scope so that if it\n   is called recursively it can remember where it was.\n * Added documentation for this new option\n\nMatthew Rogers (4):\n  config: fix typo in variable name\n  config: fix config scope enum\n  config: clarify meaning of command line scoping\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt | 15 +++++---\n builtin/config.c             | 66 ++++++++++++++++++++++++++++++------\n config.c                     | 15 ++++----\n config.h                     | 19 ++++++-----\n remote.c                     |  3 +-\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       |  8 +++--\n t/t1300-config.sh            | 50 +++++++++++++++++++++++++++\n upload-pack.c                |  3 +-\n 9 files changed, 148 insertions(+), 35 deletions(-)\n\n\nbase-commit: 7a6a90c6ec48fc78c83d7090d6c1b95d8f3739c0\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v1:\n\n -:  ---------- > 1:  b40480f03a config: fix typo in variable name\n -:  ---------- > 2:  e8e05f3940 config: fix config scope enum\n -:  ---------- > 3:  8225273546 config: clarify meaning of command line scoping\n 1:  ec699bb3e6 ! 4:  92ce9b7824 config: allow user to know scope of config options\n     @@ -1,21 +1,62 @@\n      Author: Matthew Rogers <mattr94@gmail.com>\n      \n     -    config: allow user to know scope of config options\n     +    config: add '--show-scope' to print the scope of a config value\n      \n     -    Add new option --show-scope which allows a user to know what the scope\n     -    of listed config options are (local/global/system/etc.).\n     +    When a user queries config values with --show-origin, often it's\n     +    difficult to determine what the actual \"scope\" (local, global, etc.) of\n     +    a given value is based on just the origin file.\n     +\n     +    Teach 'git config' the '--show-scope' option to print the scope of all\n     +    displayed config values.  Note that we should never see anything of\n     +    \"submodule\" scope as that is only ever used by submodule-config.c when\n     +    parsing the '.gitmodules' file.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n      \n     + diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n     + --- a/Documentation/git-config.txt\n     + +++ b/Documentation/git-config.txt\n     +@@\n     + SYNOPSIS\n     + --------\n     + [verse]\n     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n     + 'git config' [<file-option>] [--type=<type>] --add name value\n     + 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n     + 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n     + 'git config' [<file-option>] --unset name [value_regex]\n     + 'git config' [<file-option>] --unset-all name [value_regex]\n     + 'git config' [<file-option>] --rename-section old_name new_name\n     + 'git config' [<file-option>] --remove-section name\n     +-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n     ++'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n     + 'git config' [<file-option>] --get-color name [default]\n     + 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n     + 'git config' [<file-option>] -e | --edit\n     +@@\n     + \tthe actual origin (config file path, ref, or blob id if\n     + \tapplicable).\n     + \n     ++--show-scope::\n     ++\tSimilar to `--show-origin` in that it augments the output of\n     ++\tall queried config options with the scope of that value \n     ++\t(local, global, system, command).\n     ++\n     + --get-colorbool name [stdout-is-tty]::\n     + \n     + \tFind the color setting for `name` (e.g. `color.diff`) and output\n     +\n       diff --git a/builtin/config.c b/builtin/config.c\n       --- a/builtin/config.c\n       +++ b/builtin/config.c\n      @@\n     - static struct git_config_source given_config_source;\n     - static int actions, type;\n     - static char *default_value;\n     --static int end_null;\n     -+static int end_nul;\n       static int respect_includes_opt = -1;\n       static struct config_options config_options;\n       static int show_origin;\n     @@ -24,69 +65,41 @@\n       #define ACTION_GET (1<<0)\n       #define ACTION_GET_ALL (1<<1)\n      @@\n     - \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n     - \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n     - \tOPT_GROUP(N_(\"Other\")),\n     --\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n     -+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n       \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n       \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n       \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n     -+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (system, global, local, command line)\")),\n     ++\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n       \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n       \tOPT_END(),\n       };\n      @@\n     - \n     - static void show_config_origin(struct strbuf *buf)\n     - {\n     --\tconst char term = end_null ? '\\0' : '\\t';\n     -+\tconst char term = end_nul ? '\\0' : '\\t';\n     - \n     - \tstrbuf_addstr(buf, current_config_origin_type());\n     - \tstrbuf_addch(buf, ':');\n     --\tif (end_null)\n     -+\tif (end_nul)\n     - \t\tstrbuf_addstr(buf, current_config_name());\n     - \telse\n     - \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n       \tstrbuf_addch(buf, term);\n       }\n       \n      +static const char *scope_to_string(enum config_scope scope) {\n     -+\t/*\n     -+\t * --local, --global, and --system work the same as --file so there's\n     -+\t * no easy way for the parser to tell the difference when it is\n     -+\t * setting the scope, so we use our information about which options\n     -+\t * were passed\n     -+\t */\n     -+\tif (use_local_config || scope == CONFIG_SCOPE_REPO) {\n     ++\tswitch (scope) {\n     ++\tcase CONFIG_SCOPE_LOCAL:\n      +\t\treturn \"local\";\n     -+\t} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {\n     ++\tcase CONFIG_SCOPE_GLOBAL:\n      +\t\treturn \"global\";\n     -+\t} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {\n     ++\tcase CONFIG_SCOPE_SYSTEM:\n      +\t\treturn \"system\";\n     -+\t} else if (given_config_source.use_stdin ||\n     -+\t\tgiven_config_source.blob ||\n     -+\t\tgiven_config_source.file ||\n     -+\t\tscope == CONFIG_SCOPE_CMDLINE) {\n     -+\t\treturn \"command line\";\n     -+\t} else {\n     ++\tcase CONFIG_SCOPE_WORKTREE:\n     ++\t\treturn \"worktree\";\n     ++\tcase CONFIG_SCOPE_COMMAND:\n     ++\t\treturn \"command\";\n     ++\tcase CONFIG_SCOPE_SUBMODULE:\n     ++\t\treturn \"submodule\";\n     ++\tdefault:\n      +\t\treturn \"unknown\";\n      +\t}\n      +}\n      +\n     -+static void show_config_scope(struct strbuf *buf)\n     -+{\n     ++static void show_config_scope(struct strbuf *buf) {\n      +\tconst char term = end_nul ? '\\0' : '\\t';\n      +\tconst char *scope = scope_to_string(current_config_scope());\n      +\n     -+\tstrbuf_addch(buf, '(');\n     -+\tif (end_nul)\n     -+\t\tstrbuf_addstr(buf, N_(scope));\n     -+\telse\n     -+\t\tquote_c_style(scope, buf, NULL, 0);\n     -+\tstrbuf_addch(buf, ')');\n     ++\tstrbuf_addstr(buf, N_(scope));\n      +\tstrbuf_addch(buf, term);\n      +}\n      +\n     @@ -96,33 +109,188 @@\n      +\tif (show_origin || show_scope) {\n       \t\tstruct strbuf buf = STRBUF_INIT;\n      -\t\tshow_config_origin(&buf);\n     --\t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n      +\t\tif (show_scope)\n      +\t\t\tshow_config_scope(&buf);\n      +\t\tif (show_origin)\n      +\t\t\tshow_config_origin(&buf);\n     -+\t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_nul\" is set. */\n     + \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n       \t\tfwrite(buf.buf, 1, buf.len, stdout);\n       \t\tstrbuf_release(&buf);\n     - \t}\n      @@\n       \n       static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n       {\n      +\tif (show_scope)\n     -+\t\tshow_config_scope(buf);\n     ++\t\tshow_config_origin(buf);\n       \tif (show_origin)\n       \t\tshow_config_origin(buf);\n       \tif (show_keys)\n      @@\n     - \t\tconfig_options.git_dir = get_git_dir();\n     + \tint nongit = !startup_info->have_repository;\n     + \tchar *value;\n     + \n     ++\n     ++\n     + \tgiven_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));\n     + \n     + \targc = parse_options(argc, argv, prefix, builtin_config_options,\n     +@@\n     + \t\t\t!strcmp(given_config_source.file, \"-\")) {\n     + \t\tgiven_config_source.file = NULL;\n     + \t\tgiven_config_source.use_stdin = 1;\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     + \t}\n     + \n     + \tif (use_global_config) {\n     +@@\n     + \t\t\t */\n     + \t\t\tdie(_(\"$HOME not set\"));\n     + \n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n     ++\n     + \t\tif (access_or_warn(user_config, R_OK, 0) &&\n     + \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n     + \t\t\tgiven_config_source.file = xdg_config;\n     +@@\n     + \t\t\tfree(xdg_config);\n     + \t\t}\n     + \t}\n     +-\telse if (use_system_config)\n     ++\telse if (use_system_config) {\n     + \t\tgiven_config_source.file = git_etc_gitconfig();\n     +-\telse if (use_local_config)\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n     ++\t} else if (use_local_config) {\n     + \t\tgiven_config_source.file = git_pathdup(\"config\");\n     +-\telse if (use_worktree_config) {\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n     ++\t} else if (use_worktree_config) {\n     + \t\tstruct worktree **worktrees = get_worktrees(0);\n     + \t\tif (repository_format_worktree_config)\n     + \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n     +@@\n     + \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n     + \t\telse\n     + \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n     + \t\tfree_worktrees(worktrees);\n     + \t} else if (given_config_source.file) {\n     + \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n     + \t\t\tgiven_config_source.file =\n     + \t\t\t\tprefix_filename(prefix, given_config_source.file);\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     ++\t} else if (given_config_source.blob) {\n     ++\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     + \t}\n     + \n     ++\n     + \tif (respect_includes_opt == -1)\n     + \t\tconfig_options.respect_includes = !given_config_source.file;\n     + \telse\n     +\n     + diff --git a/config.c b/config.c\n     + --- a/config.c\n     + +++ b/config.c\n     +@@\n     + \tchar *xdg_config = xdg_config_home(\"config\");\n     + \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n     + \tchar *repo_config;\n     ++\tenum config_scope prev_parsing_scope = current_parsing_scope;\n     + \n     + \tif (opts->commondir)\n     + \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n     +@@\n     + \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n     + \t\tdie(_(\"unable to parse command-line config\"));\n     + \n     +-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n     ++\tcurrent_parsing_scope = prev_parsing_scope;\n     + \tfree(xdg_config);\n     + \tfree(user_config);\n     + \tfree(repo_config);\n     +@@\n     + \t\tdata = &inc;\n       \t}\n       \n     --\tif (end_null) {\n     -+\tif (end_nul) {\n     - \t\tterm = '\\0';\n     - \t\tdelim = '\\n';\n     - \t\tkey_delim = '\\n';\n     ++\tif (config_source)\n     ++\t\tcurrent_parsing_scope = config_source->scope;\n     ++\n     + \t/*\n     + \t * If we have a specific filename, use it. Otherwise, follow the\n     + \t * regular lookup sequence.\n     +\n     + diff --git a/config.h b/config.h\n     + --- a/config.h\n     + +++ b/config.h\n     +@@\n     + \n     + #define CONFIG_REGEX_NONE ((void *)1)\n     + \n     ++enum config_scope {\n     ++\tCONFIG_SCOPE_UNKNOWN = 0,\n     ++\tCONFIG_SCOPE_SYSTEM,\n     ++\tCONFIG_SCOPE_GLOBAL,\n     ++\tCONFIG_SCOPE_LOCAL,\n     ++\tCONFIG_SCOPE_WORKTREE,\n     ++\tCONFIG_SCOPE_COMMAND,\n     ++\tCONFIG_SCOPE_SUBMODULE,\n     ++};\n     ++\n     + struct git_config_source {\n     + \tunsigned int use_stdin:1;\n     + \tconst char *file;\n     + \tconst char *blob;\n     ++\tenum config_scope scope;\n     + };\n     + \n     + enum config_origin_type {\n     +@@\n     + \n     + int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n     + \n     +-enum config_scope {\n     +-\tCONFIG_SCOPE_UNKNOWN = 0,\n     +-\tCONFIG_SCOPE_SYSTEM,\n     +-\tCONFIG_SCOPE_GLOBAL,\n     +-\tCONFIG_SCOPE_LOCAL,\n     +-\tCONFIG_SCOPE_WORKTREE,\n     +-\tCONFIG_SCOPE_COMMAND,\n     +-};\n     +-\n     + enum config_scope current_config_scope(void);\n     + const char *current_config_origin_type(void);\n     + const char *current_config_name(void);\n     +\n     + diff --git a/submodule-config.c b/submodule-config.c\n     + --- a/submodule-config.c\n     + +++ b/submodule-config.c\n     +@@\n     + static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n     + {\n     + \tif (repo->worktree) {\n     +-\t\tstruct git_config_source config_source = { 0 };\n     ++\t\tstruct git_config_source config_source = {\n     ++\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n     ++\t\t};\n     + \t\tconst struct config_options opts = { 0 };\n     + \t\tstruct object_id oid;\n     + \t\tchar *file;\n     +\n     + diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n     + --- a/t/helper/test-config.c\n     + +++ b/t/helper/test-config.c\n     +@@\n     + \t\treturn \"repo\";\n     + \tcase CONFIG_SCOPE_WORKTREE:\n     + \t\treturn \"worktree\";\n     ++\tcase CONFIG_SCOPE_SUBMODULE:\n     ++\t\treturn \"submodule\";\n     + \tcase CONFIG_SCOPE_COMMAND:\n     +-\t\treturn \"command\";\n     ++\t\treturn \"cmdline\";\n     + \tdefault:\n     + \t\treturn \"unknown\";\n     + \t}\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n     @@ -131,18 +299,17 @@\n       \ttest_cmp expect output\n       '\n       \n     -+\n      +test_expect_success '--show-scope with --list' '\n      +\tcat >expect <<-EOF &&\n     -+\t\t(global)\tuser.global=true\n     -+\t\t(global)\tuser.override=global\n     -+\t\t(global)\tinclude.path=$INCLUDE_DIR/absolute.include\n     -+\t\t(global)\tuser.absolute=include\n     -+\t\t(local)\tuser.local=true\n     -+\t\t(local)\tuser.override=local\n     -+\t\t(local)\tinclude.path=../include/relative.include\n     -+\t\t(local)\tuser.relative=include\n     -+\t\t(command line)\tuser.cmdline=true\n     ++\t\tglobal\tuser.global=true\n     ++\t\tglobal\tuser.override=global\n     ++\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n     ++\t\tglobal\tuser.absolute=include\n     ++\t\tlocal\tuser.local=true\n     ++\t\tlocal\tuser.override=local\n     ++\t\tlocal\tinclude.path=../include/relative.include\n     ++\t\tlocal\tuser.relative=include\n     ++\t\tcommand\tuser.cmdline=true\n      +\tEOF\n      +\tgit -c user.cmdline=true config --list --show-scope >output &&\n      +\ttest_cmp expect output\n     @@ -151,16 +318,16 @@\n      +test_expect_success !MINGW '--show-scope with --blob' '\n      +\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n      +\tcat >expect <<-EOF &&\n     -+\t\t(command line)\tuser.custom=true\n     ++\t\tcommand\tuser.custom=true\n      +\tEOF\n      +\tgit config --blob=$blob --show-scope --list >output &&\n      +\ttest_cmp expect output\n      +'\n      +test_expect_success '--show-scope with --local' '\n      +\tcat >expect <<-\\EOF &&\n     -+\t\t(local)\tuser.local=true\n     -+\t\t(local)\tuser.override=local\n     -+\t\t(local)\tinclude.path=../include/relative.include\n     ++\t\tlocal\tuser.local=true\n     ++\t\tlocal\tuser.override=local\n     ++\t\tlocal\tinclude.path=../include/relative.include\n      +\tEOF\n      +\tgit config --local --list --show-scope >output &&\n      +\ttest_cmp expect output\n     @@ -168,15 +335,15 @@\n      +\n      +test_expect_success '--show-scope with --show-origin' '\n      +\tcat >expect <<-EOF &&\n     -+\t\t(global)\tfile:$HOME/.gitconfig\tuser.global=true\n     -+\t\t(global)\tfile:$HOME/.gitconfig\tuser.override=global\n     -+\t\t(global)\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n     -+\t\t(global)\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n     -+\t\t(local)\tfile:.git/config\tuser.local=true\n     -+\t\t(local)\tfile:.git/config\tuser.override=local\n     -+\t\t(local)\tfile:.git/config\tinclude.path=../include/relative.include\n     -+\t\t(local)\tfile:.git/../include/relative.include\tuser.relative=include\n     -+\t\t(command line)\tcommand line:\tuser.cmdline=true\n     ++\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n     ++\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n     ++\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n     ++\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n     ++\t\tlocal\tfile:.git/config\tuser.local=true\n     ++\t\tlocal\tfile:.git/config\tuser.override=local\n     ++\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n     ++\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n     ++\t\tcommand\tcommand line:\tuser.cmdline=true\n      +\tEOF\n      +\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n      +\ttest_cmp expect output\n\n-- \ngitgitgadget\n"},{"id":"389528","messageId":"82252735467d876b4726f512a02cc44d271696ca.1578565001.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","subject":"[PATCH v2 3/4] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-09T10:16:40Z","receivedAt":"2020-01-09T10:16:51Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  This is a little bit too specific\nas there are other methods to pass config values so that the last for a\nsingle command (namely --file and --blob).  As the \"visibility\" of config\nvalues passed by these situations is common, we unify them as having a\nscope of \"command\" rather than \"command line\".\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 2 +-\n config.h               | 2 +-\n t/helper/test-config.c | 4 ++--\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 447a013a15..f319a3d6a0 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \ndiff --git a/config.h b/config.h\nindex 284d92fb0e..f383a71404 100644\n--- a/config.h\n+++ b/config.h\n@@ -300,7 +300,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n \n enum config_scope current_config_scope(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 6695e463eb..78bbb9eb98 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\n-- \ngitgitgadget\n\n"},{"id":"389529","messageId":"92ce9b782429248197bb87cfa11c89082304218f.1578565002.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","subject":"[PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-09T10:16:41Z","receivedAt":"2020-01-09T10:16:51Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n Documentation/git-config.txt | 15 ++++++----\n builtin/config.c             | 56 ++++++++++++++++++++++++++++++++----\n config.c                     |  6 +++-\n config.h                     | 20 +++++++------\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       |  4 ++-\n t/t1300-config.sh            | 50 ++++++++++++++++++++++++++++++++\n 7 files changed, 133 insertions(+), 22 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..2e47765aab 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value \n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..0367d28ec1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,41 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static const char *scope_to_string(enum config_scope scope) {\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+static void show_config_scope(struct strbuf *buf) {\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = scope_to_string(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +245,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_origin(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -599,6 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \tint nongit = !startup_info->have_repository;\n \tchar *value;\n \n+\n+\n \tgiven_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));\n \n \targc = parse_options(argc, argv, prefix, builtin_config_options,\n@@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex f319a3d6a0..035fc8fb29 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\ndiff --git a/config.h b/config.h\nindex f383a71404..91f851e925 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,10 +35,21 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n+};\n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -294,15 +305,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 78bbb9eb98..aae2c6fc9e 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n \tcase CONFIG_SCOPE_COMMAND:\n-\t\treturn \"command\";\n+\t\treturn \"cmdline\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..6cecc80b18 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1766,6 +1766,56 @@ test_expect_success !MINGW '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tuser.global=true\n+\t\tglobal\tuser.override=global\n+\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tuser.absolute=include\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\t\tlocal\tuser.relative=include\n+\t\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\t\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\t\tlocal\tfile:.git/config\tuser.local=true\n+\t\tlocal\tfile:.git/config\tuser.override=local\n+\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\t\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"389540","messageId":"xmqqpnfszbyh.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"e8e05f39407365a1bf5008820267d362e0cbffd6.1578565001.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 2/4] config: fix config scope enum","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-09T19:06:30Z","receivedAt":"2020-01-09T19:06:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Previously when iterating through git config variables, worktree config\n> and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n> never a problem before as no one had needed to differentiate between the\n> two cases.\n\nHmph, then \"fix\" on the title is a bit misleading, no?  \n\nThe enum may not have been as fine grained as you would have liked,\nbut if there was nothing broken, then we are doing this not to \"fix\"\nanything.  \n\nA more important thing to explain would probably be why we\n(i.e. those who propose this change, those who give favoriable\nreviews to it, and those who accept it change to the system) would\nwant to see finer-grained classification.  What do we expect to be\nable to do with the resulting finer-grained set that we wouldn't be\nable to with the original, and why is it a good thing?  That is what\nreaders of the proposed log message of this change would want to\nsee, I would think.\n\n> Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL\n> to reflect its new, more specific meaning.\n>\n> The clients of 'current_config_scope()' who cared about\n> CONFIG_SCOPE_REPO are also modified to similarly care about\n> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  config.c               | 7 ++-----\n>  config.h               | 3 ++-\n>  remote.c               | 3 ++-\n>  t/helper/test-config.c | 4 +++-\n>  upload-pack.c          | 3 ++-\n>  5 files changed, 11 insertions(+), 9 deletions(-)\n>\n> diff --git a/config.c b/config.c\n> index d75f88ca0c..447a013a15 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n>  \t\tret += git_config_from_file(fn, user_config, data);\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n>  \tif (!opts->ignore_repo && repo_config &&\n>  \t    !access_or_die(repo_config, R_OK, 0))\n>  \t\tret += git_config_from_file(fn, repo_config, data);\n>  \n> -\t/*\n> -\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n> -\t * But let's not complicate things before it's actually needed.\n> -\t */\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n>  \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n>  \t\tchar *path = git_pathdup(\"config.worktree\");\n>  \t\tif (!access_or_die(path, R_OK, 0))\n> diff --git a/config.h b/config.h\n> index 91fd4c5e96..284d92fb0e 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -298,7 +298,8 @@ enum config_scope {\n>  \tCONFIG_SCOPE_UNKNOWN = 0,\n>  \tCONFIG_SCOPE_SYSTEM,\n>  \tCONFIG_SCOPE_GLOBAL,\n> -\tCONFIG_SCOPE_REPO,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n>  \tCONFIG_SCOPE_CMDLINE,\n>  };\n>  \n> diff --git a/remote.c b/remote.c\n> index 5c4666b53a..593ce297ed 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n>  \t}\n>  \tremote = make_remote(name, namelen);\n>  \tremote->origin = REMOTE_CONFIG;\n> -\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n> +\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n> +\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n>  \t\tremote->configured_in_repo = 1;\n>  \tif (!strcmp(subkey, \"mirror\"))\n>  \t\tremote->mirror = git_config_bool(key, value);\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 214003d5b2..6695e463eb 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"system\";\n>  \tcase CONFIG_SCOPE_GLOBAL:\n>  \t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> +\tcase CONFIG_SCOPE_LOCAL:\n>  \t\treturn \"repo\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n>  \tcase CONFIG_SCOPE_CMDLINE:\n>  \t\treturn \"cmdline\";\n>  \tdefault:\n> diff --git a/upload-pack.c b/upload-pack.c\n> index a00d7ece6b..c53249cac1 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n>  \t\tprecomposed_unicode = git_config_bool(var, value);\n>  \t}\n>  \n> -\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n> +\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n> +\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n>  \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n>  \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n>  \t}\n"},{"id":"389541","messageId":"xmqqlfqgzbwp.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"b40480f03a5643761bd06d4b9c495a99b98a1ac8.1578565001.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 1/4] config: fix typo in variable name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-09T19:07:34Z","receivedAt":"2020-01-09T19:07:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> In git config use of the end_null variable to determine if we should be\n> null terminating our output.  While it is correct to say a string is\n> \"null terminated\" the character is actually the \"nul\" character, so this\n> malapropism is being fixed.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  builtin/config.c | 10 +++++-----\n>  1 file changed, 5 insertions(+), 5 deletions(-)\n\nObviously correct.\n\nMalapropism is a new word in \"git log\" output in our history ;-)\n\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 98d65bc0ad..52a904cfb1 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -29,7 +29,7 @@ static int use_worktree_config;\n>  static struct git_config_source given_config_source;\n>  static int actions, type;\n>  static char *default_value;\n> -static int end_null;\n> +static int end_nul;\n>  static int respect_includes_opt = -1;\n>  static struct config_options config_options;\n>  static int show_origin;\n> @@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n>  \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n>  \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n>  \tOPT_GROUP(N_(\"Other\")),\n> -\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n> +\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n>  \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n>  \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n>  \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n> @@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n>  \n>  static void show_config_origin(struct strbuf *buf)\n>  {\n> -\tconst char term = end_null ? '\\0' : '\\t';\n> +\tconst char term = end_nul ? '\\0' : '\\t';\n>  \n>  \tstrbuf_addstr(buf, current_config_origin_type());\n>  \tstrbuf_addch(buf, ':');\n> -\tif (end_null)\n> +\tif (end_nul)\n>  \t\tstrbuf_addstr(buf, current_config_name());\n>  \telse\n>  \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n> @@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\tconfig_options.git_dir = get_git_dir();\n>  \t}\n>  \n> -\tif (end_null) {\n> +\tif (end_nul) {\n>  \t\tterm = '\\0';\n>  \t\tdelim = '\\n';\n>  \t\tkey_delim = '\\n';\n"},{"id":"389544","messageId":"xmqqh814zbm0.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"82252735467d876b4726f512a02cc44d271696ca.1578565001.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 3/4] config: clarify meaning of command line scoping","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-09T19:13:59Z","receivedAt":"2020-01-09T19:19:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\n> values passed in via the -c option.  This is a little bit too specific\n> as there are other methods to pass config values so that the last for a\n> single command (namely --file and --blob).\n\nSorry, but I cannot parse this, especially around \"so that the last\nfor ...\" part.\n\n> As the \"visibility\" of config\n> values passed by these situations is common, we unify them as having a\n> scope of \"command\" rather than \"command line\".\n\nIs the \"unification\" something done by this patch?  It does not\nappear to be so.  The existing code already was using CMDLINE to\ncall \"git -c VAR=VAL\" and also something else (which is not clear to\nme, unfortunately, probably because I failed to parse the above\nX-<), and this step renames CMDLINE to COMMAND perhaps because\nCMDLINE has too strong connotation with the \"-c\" thing and much less\nwith the other thing (which is not clear to me, unfortunately) and\nyou found that renaming it to COMMAND would cover both cases better?\n\nI also do not get what you meant by \"visibility\", but it probably is\nprimarily because it is not clear what \"the other thing\" is.\n\n\n\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  config.c               | 2 +-\n>  config.h               | 2 +-\n>  t/helper/test-config.c | 4 ++--\n>  3 files changed, 4 insertions(+), 4 deletions(-)\n>\n> diff --git a/config.c b/config.c\n> index 447a013a15..f319a3d6a0 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \t\tfree(path);\n>  \t}\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n>  \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n>  \t\tdie(_(\"unable to parse command-line config\"));\n>  \n> diff --git a/config.h b/config.h\n> index 284d92fb0e..f383a71404 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -300,7 +300,7 @@ enum config_scope {\n>  \tCONFIG_SCOPE_GLOBAL,\n>  \tCONFIG_SCOPE_LOCAL,\n>  \tCONFIG_SCOPE_WORKTREE,\n> -\tCONFIG_SCOPE_CMDLINE,\n> +\tCONFIG_SCOPE_COMMAND,\n>  };\n>  \n>  enum config_scope current_config_scope(void);\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 6695e463eb..78bbb9eb98 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"repo\";\n>  \tcase CONFIG_SCOPE_WORKTREE:\n>  \t\treturn \"worktree\";\n> -\tcase CONFIG_SCOPE_CMDLINE:\n> -\t\treturn \"cmdline\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n>  \tdefault:\n>  \t\treturn \"unknown\";\n>  \t}\n"},{"id":"389545","messageId":"xmqqd0bsz9xm.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"92ce9b782429248197bb87cfa11c89082304218f.1578565002.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-09T19:50:13Z","receivedAt":"2020-01-09T19:50:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> When a user queries config values with --show-origin, often it's\n> difficult to determine what the actual \"scope\" (local, global, etc.) of\n> a given value is based on just the origin file.\n>\n> Teach 'git config' the '--show-scope' option to print the scope of all\n> displayed config values.  Note that we should never see anything of\n> \"submodule\" scope as that is only ever used by submodule-config.c when\n> parsing the '.gitmodules' file.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  Documentation/git-config.txt | 15 ++++++----\n>  builtin/config.c             | 56 ++++++++++++++++++++++++++++++++----\n>  config.c                     |  6 +++-\n>  config.h                     | 20 +++++++------\n>  submodule-config.c           |  4 ++-\n>  t/helper/test-config.c       |  4 ++-\n>  t/t1300-config.sh            | 50 ++++++++++++++++++++++++++++++++\n>  7 files changed, 133 insertions(+), 22 deletions(-)\n>\n> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n> index 899e92a1c9..2e47765aab 100644\n> --- a/Documentation/git-config.txt\n> +++ b/Documentation/git-config.txt\n> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n>  SYNOPSIS\n>  --------\n>  [verse]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n>  'git config' [<file-option>] [--type=<type>] --add name value\n>  'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n>  'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n>  'git config' [<file-option>] --unset name [value_regex]\n>  'git config' [<file-option>] --unset-all name [value_regex]\n>  'git config' [<file-option>] --rename-section old_name new_name\n>  'git config' [<file-option>] --remove-section name\n> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n> +'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n>  'git config' [<file-option>] --get-color name [default]\n>  'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n>  'git config' [<file-option>] -e | --edit\n> @@ -222,6 +222,11 @@ Valid `<type>`'s include:\n>  \tthe actual origin (config file path, ref, or blob id if\n>  \tapplicable).\n>  \n> +--show-scope::\n> +\tSimilar to `--show-origin` in that it augments the output of\n> +\tall queried config options with the scope of that value \n> +\t(local, global, system, command).\n> +\n>  --get-colorbool name [stdout-is-tty]::\n>  \n>  \tFind the color setting for `name` (e.g. `color.diff`) and output\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 52a904cfb1..0367d28ec1 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -33,6 +33,7 @@ static int end_nul;\n>  static int respect_includes_opt = -1;\n>  static struct config_options config_options;\n>  static int show_origin;\n> +static int show_scope;\n>  \n>  #define ACTION_GET (1<<0)\n>  #define ACTION_GET_ALL (1<<1)\n> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n>  \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n>  \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n>  \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n> +\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n>  \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n>  \tOPT_END(),\n>  };\n> @@ -189,11 +191,41 @@ static void show_config_origin(struct strbuf *buf)\n>  \tstrbuf_addch(buf, term);\n>  }\n>  \n> +static const char *scope_to_string(enum config_scope scope) {\n\nStyle: the outermost opening and closing parentheses of a functiond\ndefinition sit on their own lines by themselves.  Same for the next\none.\n\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n> +\tdefault:\n> +\t\treturn \"unknown\";\n\nMakes me wonder if this wants to be done via a table, which would\nlater allow a parser to map in the other direction, taking a string\nand returning the corresponding enum, more easily (imagine a yet to\nbe invented feature to \"list config settings for only this scope\").\n\n> +\t}\n> +}\n> +\n> +static void show_config_scope(struct strbuf *buf) {\n> +\tconst char term = end_nul ? '\\0' : '\\t';\n> +\tconst char *scope = scope_to_string(current_config_scope());\n> +\n> +\tstrbuf_addstr(buf, N_(scope));\n> +\tstrbuf_addch(buf, term);\n> +}\n> +\n>  static int show_all_config(const char *key_, const char *value_, void *cb)\n>  {\n> -\tif (show_origin) {\n> +\tif (show_origin || show_scope) {\n>  \t\tstruct strbuf buf = STRBUF_INIT;\n> -\t\tshow_config_origin(&buf);\n> +\t\tif (show_scope)\n> +\t\t\tshow_config_scope(&buf);\n> +\t\tif (show_origin)\n> +\t\t\tshow_config_origin(&buf);\n>  \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n>  \t\tfwrite(buf.buf, 1, buf.len, stdout);\n>  \t\tstrbuf_release(&buf);\n> @@ -213,6 +245,8 @@ struct strbuf_list {\n>  \n>  static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n>  {\n> +\tif (show_scope)\n> +\t\tshow_config_origin(buf);\n>  \tif (show_origin)\n>  \t\tshow_config_origin(buf);\n\nShouldn't one of these show scope instead of origin?  I wonder how\nthe tests I see later in the patch could have passed with this.\n\n>  \tif (show_keys)\n> @@ -599,6 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \tint nongit = !startup_info->have_repository;\n>  \tchar *value;\n>  \n> +\n> +\n\nUnnecessary edit?\n\n>  \tgiven_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));\n>  \n>  \targc = parse_options(argc, argv, prefix, builtin_config_options,\n> @@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\t\t!strcmp(given_config_source.file, \"-\")) {\n>  \t\tgiven_config_source.file = NULL;\n>  \t\tgiven_config_source.use_stdin = 1;\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n>  \t}\n>  \n>  \tif (use_global_config) {\n> @@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\t\t */\n>  \t\t\tdie(_(\"$HOME not set\"));\n>  \n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n> +\n>  \t\tif (access_or_warn(user_config, R_OK, 0) &&\n>  \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n>  \t\t\tgiven_config_source.file = xdg_config;\n> @@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\t\tfree(xdg_config);\n>  \t\t}\n>  \t}\n> -\telse if (use_system_config)\n> +\telse if (use_system_config) {\n>  \t\tgiven_config_source.file = git_etc_gitconfig();\n> -\telse if (use_local_config)\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n> +\t} else if (use_local_config) {\n>  \t\tgiven_config_source.file = git_pathdup(\"config\");\n> -\telse if (use_worktree_config) {\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n> +\t} else if (use_worktree_config) {\n>  \t\tstruct worktree **worktrees = get_worktrees(0);\n>  \t\tif (repository_format_worktree_config)\n>  \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n> @@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>  \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n>  \t\telse\n>  \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n>  \t\tfree_worktrees(worktrees);\n>  \t} else if (given_config_source.file) {\n>  \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n>  \t\t\tgiven_config_source.file =\n>  \t\t\t\tprefix_filename(prefix, given_config_source.file);\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n> +\t} else if (given_config_source.blob) {\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n\nThese that set scope for individual sources, not just during the\nnormal sequence, are new in this round, and I think it is an\nimprovement.\n\n>  \t}\n>  \n> +\n>  \tif (respect_includes_opt == -1)\n>  \t\tconfig_options.respect_includes = !given_config_source.file;\n>  \telse\n> diff --git a/config.c b/config.c\n> index f319a3d6a0..035fc8fb29 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tchar *xdg_config = xdg_config_home(\"config\");\n>  \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n>  \tchar *repo_config;\n> +\tenum config_scope prev_parsing_scope = current_parsing_scope;\n>  \n>  \tif (opts->commondir)\n>  \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n>  \t\tdie(_(\"unable to parse command-line config\"));\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n> +\tcurrent_parsing_scope = prev_parsing_scope;\n>  \tfree(xdg_config);\n>  \tfree(user_config);\n>  \tfree(repo_config);\n> @@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n>  \t\tdata = &inc;\n>  \t}\n>  \n> +\tif (config_source)\n> +\t\tcurrent_parsing_scope = config_source->scope;\n> +\n>  \t/*\n>  \t * If we have a specific filename, use it. Otherwise, follow the\n>  \t * regular lookup sequence.\n> diff --git a/config.h b/config.h\n> index f383a71404..91f851e925 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -35,10 +35,21 @@ struct object_id;\n>  \n>  #define CONFIG_REGEX_NONE ((void *)1)\n>  \n> +enum config_scope {\n> +\tCONFIG_SCOPE_UNKNOWN = 0,\n> +\tCONFIG_SCOPE_SYSTEM,\n> +\tCONFIG_SCOPE_GLOBAL,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n> +\tCONFIG_SCOPE_COMMAND,\n> +\tCONFIG_SCOPE_SUBMODULE,\n> +};\n> +\n>  struct git_config_source {\n>  \tunsigned int use_stdin:1;\n>  \tconst char *file;\n>  \tconst char *blob;\n> +\tenum config_scope scope;\n>  };\n>  \n>  enum config_origin_type {\n> @@ -294,15 +305,6 @@ int config_error_nonbool(const char *);\n>  \n>  int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n>  \n> -enum config_scope {\n> -\tCONFIG_SCOPE_UNKNOWN = 0,\n> -\tCONFIG_SCOPE_SYSTEM,\n> -\tCONFIG_SCOPE_GLOBAL,\n> -\tCONFIG_SCOPE_LOCAL,\n> -\tCONFIG_SCOPE_WORKTREE,\n> -\tCONFIG_SCOPE_COMMAND,\n> -};\n> -\n>  enum config_scope current_config_scope(void);\n>  const char *current_config_origin_type(void);\n>  const char *current_config_name(void);\n> diff --git a/submodule-config.c b/submodule-config.c\n> index 85064810b2..b8e97d8ae8 100644\n> --- a/submodule-config.c\n> +++ b/submodule-config.c\n> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n>  static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n>  {\n>  \tif (repo->worktree) {\n> -\t\tstruct git_config_source config_source = { 0 };\n> +\t\tstruct git_config_source config_source = {\n> +\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n> +\t\t};\n>  \t\tconst struct config_options opts = { 0 };\n>  \t\tstruct object_id oid;\n>  \t\tchar *file;\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 78bbb9eb98..aae2c6fc9e 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"repo\";\n>  \tcase CONFIG_SCOPE_WORKTREE:\n>  \t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n>  \tcase CONFIG_SCOPE_COMMAND:\n> -\t\treturn \"command\";\n> +\t\treturn \"cmdline\";\n\nOh???\n\n>  \tdefault:\n>  \t\treturn \"unknown\";\n>  \t}\n> diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> index 983a0a1583..6cecc80b18 100755\n> --- a/t/t1300-config.sh\n> +++ b/t/t1300-config.sh\n> @@ -1766,6 +1766,56 @@ test_expect_success !MINGW '--show-origin blob ref' '\n>  \ttest_cmp expect output\n>  '\n>  \n> +test_expect_success '--show-scope with --list' '\n> +\tcat >expect <<-EOF &&\n> +\t\tglobal\tuser.global=true\n> +\t\tglobal\tuser.override=global\n> +\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\t\tglobal\tuser.absolute=include\n> +\t\tlocal\tuser.local=true\n> +\t\tlocal\tuser.override=local\n> +\t\tlocal\tinclude.path=../include/relative.include\n> +\t\tlocal\tuser.relative=include\n> +\t\tcommand\tuser.cmdline=true\n> +\tEOF\n> +\tgit -c user.cmdline=true config --list --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success !MINGW '--show-scope with --blob' '\n> +\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n> +\tcat >expect <<-EOF &&\n> +\t\tcommand\tuser.custom=true\n> +\tEOF\n> +\tgit config --blob=$blob --show-scope --list >output &&\n> +\ttest_cmp expect output\n> +'\n> +test_expect_success '--show-scope with --local' '\n> +\tcat >expect <<-\\EOF &&\n> +\t\tlocal\tuser.local=true\n> +\t\tlocal\tuser.override=local\n> +\t\tlocal\tinclude.path=../include/relative.include\n> +\tEOF\n> +\tgit config --local --list --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success '--show-scope with --show-origin' '\n> +\tcat >expect <<-EOF &&\n> +\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n> +\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n> +\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n> +\t\tlocal\tfile:.git/config\tuser.local=true\n> +\t\tlocal\tfile:.git/config\tuser.override=local\n> +\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n> +\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n> +\t\tcommand\tcommand line:\tuser.cmdline=true\n> +\tEOF\n> +\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n>  test_expect_success '--local requires a repo' '\n>  \t# we expect 128 to ensure that we do not simply\n>  \t# fail to find anything and return code \"1\"\n"},{"id":"389555","messageId":"CAOjrSZvj5ne2Cyt=X-dCntjy9-Hvwn_DJXMPGR83=dZHU8R=1Q@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqlfqgzbwp.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 1/4] config: fix typo in variable name","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-09T23:22:02Z","receivedAt":"2020-01-09T23:22:17Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":">\n> Malapropism is a new word in \"git log\" output in our history ;-)\n>\n\nYeah, I remember my coworker saying that to me the day I wrote the\nmessage and it was just stuck in my head\n"},{"id":"389556","messageId":"CAOjrSZu4PRR17fjqJNK6r61OKJHchR7nkgcX3VBzLEZHb+BUBA@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqpnfszbyh.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 2/4] config: fix config scope enum","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-09T23:29:25Z","receivedAt":"2020-01-09T23:29:39Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"On Thu, Jan 9, 2020 at 2:06 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > From: Matthew Rogers <mattr94@gmail.com>\n> >\n> > Previously when iterating through git config variables, worktree config\n> > and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n> > never a problem before as no one had needed to differentiate between the\n> > two cases.\n>\n> Hmph, then \"fix\" on the title is a bit misleading, no?\n>\n> The enum may not have been as fine grained as you would have liked,\n> but if there was nothing broken, then we are doing this not to \"fix\"\n> anything.\n>\n\nI see where you're coming from, but I would definitely consider this a \"fix\"\nin that it's something that (as explained in the deleted comment) should\nhave been this way from the start but was unnecessary as no one had a\nneed for it yet.  But I definitely wouldn't be against changing the phrasing\nto something like \"clean up\" or whatever your preferred wording would be.\n\n> A more important thing to explain would probably be why we\n> (i.e. those who propose this change, those who give favoriable\n> reviews to it, and those who accept it change to the system) would\n> want to see finer-grained classification.  What do we expect to be\n> able to do with the resulting finer-grained set that we wouldn't be\n> able to with the original, and why is it a good thing?  That is what\n> readers of the proposed log message of this change would want to\n> see, I would think.\n>\n\nThis is really more prep for patch 4 later on in this series, as a user who\nran the proposed '--show-scope' later on in the series would care what\nwas \"worktree\" vs \"local\".\n\nRegardless, I think the two options I have would be to amend the commit\nmessage with that extra information or roll it together with patch 4\n"},{"id":"389557","messageId":"CAOjrSZu_fobU9bwDogt3YhR7C6amx=FgzYCDo_sU2_tR=Koj0g@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqh814zbm0.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 3/4] config: clarify meaning of command line scoping","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-09T23:41:08Z","receivedAt":"2020-01-09T23:41:22Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"On Thu, Jan 9, 2020 at 2:14 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > From: Matthew Rogers <mattr94@gmail.com>\n> >\n> > CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\n> > values passed in via the -c option.  This is a little bit too specific\n> > as there are other methods to pass config values so that the last for a\n> > single command (namely --file and --blob).\n>\n> Sorry, but I cannot parse this, especially around \"so that the last\n> for ...\" part.\n>\n\nMy bad, I guess I must have not read as carefully as I thought I did.\nIt should read:\n\"... there are other methods to pass config values so that _they_ last\nfor a single command ...\"\n\n> > As the \"visibility\" of config\n> > values passed by these situations is common, we unify them as having a\n> > scope of \"command\" rather than \"command line\".\n>\n> Is the \"unification\" something done by this patch?  It does not\n> appear to be so.  The existing code already was using CMDLINE to\n> call \"git -c VAR=VAL\" and also something else (which is not clear to\n> me, unfortunately, probably because I failed to parse the above\n> X-<), and this step renames CMDLINE to COMMAND perhaps because\n> CMDLINE has too strong connotation with the \"-c\" thing and much less\n> with the other thing (which is not clear to me, unfortunately) and\n> you found that renaming it to COMMAND would cover both cases better?\n\nEssentially, the \"unification\" was referring to more the unification of all the\nthings that affect configuration only for the duration of a specific command.\n\nThe gist of this patch was to say \"There are a few ways besides -c to pass\na configuration option that lasts for a single command, so it makes sense\nto broaden that scope.\".  The change is definitely justified in that COMMAND\ncommunicates that much clearer than CMDLINE as REPO, GLOBAL, SYSTEM\nall describe the thing that can see the configuration options, and\nit's specifically the\ncommand the can see the -c options and not the command line as a whole.\n\n>\n> I also do not get what you meant by \"visibility\", but it probably is\n> primarily because it is not clear what \"the other thing\" is.\n\nI was using visibility as another way to conceptualize scoping.  A\nscope more or less determines who can \"see\" a thing, so maybe that\nlanguage was a little bit too much in my head.\n\nThe issue is that currently the code doesn't care about any of that (as only -c\noptions actually have COMMAND scoping), so maybe I should roll it into the\nnext patch of the series?  As that introduces code that actually cares about the\ndifference?\n"},{"id":"389558","messageId":"CAOjrSZviSf+b6-MMavyAntcp0MfK91N-cZEyJYiwJ8OqEbgXYQ@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqd0bsz9xm.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-09T23:47:36Z","receivedAt":"2020-01-09T23:47:52Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"> > +     switch (scope) {\n> > +     case CONFIG_SCOPE_LOCAL:\n> > +             return \"local\";\n> > +     case CONFIG_SCOPE_GLOBAL:\n> > +             return \"global\";\n> > +     case CONFIG_SCOPE_SYSTEM:\n> > +             return \"system\";\n> > +     case CONFIG_SCOPE_WORKTREE:\n> > +             return \"worktree\";\n> > +     case CONFIG_SCOPE_COMMAND:\n> > +             return \"command\";\n> > +     case CONFIG_SCOPE_SUBMODULE:\n> > +             return \"submodule\";\n> > +     default:\n> > +             return \"unknown\";\n>\n> Makes me wonder if this wants to be done via a table, which would\n> later allow a parser to map in the other direction, taking a string\n> and returning the corresponding enum, more easily (imagine a yet to\n> be invented feature to \"list config settings for only this scope\").\n\nI was thinking the same but then I realized such an option already exists,\n--local and company.\n\n>\n> > +     }\n> > +}\n> > +\n> > +static void show_config_scope(struct strbuf *buf) {\n> > +     const char term = end_nul ? '\\0' : '\\t';\n> > +     const char *scope = scope_to_string(current_config_scope());\n> > +\n> > +     strbuf_addstr(buf, N_(scope));\n> > +     strbuf_addch(buf, term);\n> > +}\n> > +\n> >  static int show_all_config(const char *key_, const char *value_, void *cb)\n> >  {\n> > -     if (show_origin) {\n> > +     if (show_origin || show_scope) {\n> >               struct strbuf buf = STRBUF_INIT;\n> > -             show_config_origin(&buf);\n> > +             if (show_scope)\n> > +                     show_config_scope(&buf);\n> > +             if (show_origin)\n> > +                     show_config_origin(&buf);\n> >               /* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n> >               fwrite(buf.buf, 1, buf.len, stdout);\n> >               strbuf_release(&buf);\n> > @@ -213,6 +245,8 @@ struct strbuf_list {\n> >\n> >  static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n> >  {\n> > +     if (show_scope)\n> > +             show_config_origin(buf);\n> >       if (show_origin)\n> >               show_config_origin(buf);\n>\n> Shouldn't one of these show scope instead of origin?  I wonder how\n> the tests I see later in the patch could have passed with this.\n>\n\nOof, that was a blunder... I think this passes the tests because none of them\nactually hits `format_config()` only `show_all_config()` so I'll definitely add\na test case for this. (and fix it while I'm at it)\n\n> > diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> > index 78bbb9eb98..aae2c6fc9e 100644\n> > --- a/t/helper/test-config.c\n> > +++ b/t/helper/test-config.c\n> > @@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)\n> >               return \"repo\";\n> >       case CONFIG_SCOPE_WORKTREE:\n> >               return \"worktree\";\n> > +     case CONFIG_SCOPE_SUBMODULE:\n> > +             return \"submodule\";\n> >       case CONFIG_SCOPE_COMMAND:\n> > -             return \"command\";\n> > +             return \"cmdline\";\n>\n> Oh???\n>\n\nI definitely got a little too excited to get this patch in, so I\ndefinitely apologize for that,\nbut thanks for the review.\n\n-- \nMatthew Rogers\n"},{"id":"389576","messageId":"20200110115505.GA979160@coredump.intra.peff.net","threadId":"52477","inReplyTo":"b40480f03a5643761bd06d4b9c495a99b98a1ac8.1578565001.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 1/4] config: fix typo in variable name","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2020-01-10T11:55:05Z","receivedAt":"2020-01-10T11:55:08Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jan 09, 2020 at 10:16:38AM +0000, Matthew Rogers via GitGitGadget wrote:\n\n> -\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n> +\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n\nThe user-facing option is still spelled \"null\". Obviously we can't just\nchange that, but if we are trying to prefer \"nul\", should we offer both?\n\nI think we actually _do_ allow \"--nul\" because of parse-option's\nwillingness to accept a partial name. But if we wanted to advertise one\nover the other in \"-h\", then we'd have to set up the alias ourselves.\n\nInterestingly, \"xargs\" (and GNU grep) spells it as \"--null\", so perhaps\nthat's an argument to keep it as-is. Likewise if we accept that \"null\ntermination\" is a correct name, I suppose.\n\n-Peff\n"},{"id":"389991","messageId":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v2.git.1578565001.gitgitgadget@gmail.com","subject":"[PATCH v3 0/4] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-17T15:31:38Z","receivedAt":"2020-01-17T15:31:48Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v2:\n\n * Redid commit messages for content/clarity\n * Minor fixes around using --show-scope with a single value (format_config)\n\nMatthew Rogers (4):\n  config: fix typo in variable name\n  config: refine config scope enum\n  config: clarify meaning of command line scoping\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt | 15 +++++---\n builtin/config.c             | 66 ++++++++++++++++++++++++++++++------\n config.c                     | 15 ++++----\n config.h                     | 19 ++++++-----\n remote.c                     |  3 +-\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       | 10 ++++--\n t/t1300-config.sh            | 58 +++++++++++++++++++++++++++++++\n t/t1308-config-set.sh        |  2 +-\n upload-pack.c                |  3 +-\n 10 files changed, 158 insertions(+), 37 deletions(-)\n\n\nbase-commit: 232378479ee6c66206d47a9be175e3a39682aea6\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v2:\n\n 1:  b40480f03a = 1:  f5a81a4d25 config: fix typo in variable name\n 2:  e8e05f3940 ! 2:  f06f9291b7 config: fix config scope enum\n     @@ -1,14 +1,21 @@\n      Author: Matthew Rogers <mattr94@gmail.com>\n      \n     -    config: fix config scope enum\n     +    config: refine config scope enum\n      \n          Previously when iterating through git config variables, worktree config\n          and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n          never a problem before as no one had needed to differentiate between the\n     -    two cases.\n     +    two cases, but future functionality may care whether or not the config\n     +    options come from a worktree or from the repository's actual local\n     +    config file.  For example, the planned feature to add a '--show-scope'\n     +    to config to allow a user to see which scope listed config options come\n     +    from would confuse users if it just printed 'repo' rather than 'local'\n     +    or 'worktree' as the documentation would lead them to expect.  As well\n     +    as the additional benefit of making the implementation look more like\n     +    how the documentation describes the interface.\n      \n     -    Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL\n     -    to reflect its new, more specific meaning.\n     +    To accomplish this we split out what was previously considered repo\n     +    scope to be local and worktree.\n      \n          The clients of 'current_config_scope()' who cared about\n          CONFIG_SCOPE_REPO are also modified to similarly care about\n     @@ -82,6 +89,19 @@\n       \t\treturn \"cmdline\";\n       \tdefault:\n      \n     + diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n     + --- a/t/t1308-config-set.sh\n     + +++ b/t/t1308-config-set.sh\n     +@@\n     + \tvalue=from-cmdline\n     + \torigin=command line\n     + \tname=\n     +-\tscope=cmdline\n     ++\tscope=command\n     + \tEOF\n     + \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n     + \ttest_cmp expect actual\n     +\n       diff --git a/upload-pack.c b/upload-pack.c\n       --- a/upload-pack.c\n       +++ b/upload-pack.c\n 3:  8225273546 ! 3:  97b8a7641d config: clarify meaning of command line scoping\n     @@ -3,11 +3,13 @@\n          config: clarify meaning of command line scoping\n      \n          CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\n     -    values passed in via the -c option.  This is a little bit too specific\n     -    as there are other methods to pass config values so that the last for a\n     -    single command (namely --file and --blob).  As the \"visibility\" of config\n     -    values passed by these situations is common, we unify them as having a\n     -    scope of \"command\" rather than \"command line\".\n     +    values passed in via the -c option.  Options passed in using this\n     +    mechanism share similar scoping characteristics with the --file and\n     +    --blob options of the 'config' command, namely that they are only in use\n     +    for that single invocation of git, and that they supersede the normal\n     +    system/global/local hierarchy.  This patch introduces\n     +    CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\n     +    CONFIG_SCOPE_CMDLINE redundant.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n      \n 4:  92ce9b7824 ! 4:  61ff3c64b5 config: add '--show-scope' to print the scope of a config value\n     @@ -76,7 +76,8 @@\n       \tstrbuf_addch(buf, term);\n       }\n       \n     -+static const char *scope_to_string(enum config_scope scope) {\n     ++static const char *scope_to_string(enum config_scope scope)\n     ++{\n      +\tswitch (scope) {\n      +\tcase CONFIG_SCOPE_LOCAL:\n      +\t\treturn \"local\";\n     @@ -95,7 +96,8 @@\n      +\t}\n      +}\n      +\n     -+static void show_config_scope(struct strbuf *buf) {\n     ++static void show_config_scope(struct strbuf *buf)\n     ++{\n      +\tconst char term = end_nul ? '\\0' : '\\t';\n      +\tconst char *scope = scope_to_string(current_config_scope());\n      +\n     @@ -121,19 +123,10 @@\n       static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n       {\n      +\tif (show_scope)\n     -+\t\tshow_config_origin(buf);\n     ++\t\tshow_config_scope(buf);\n       \tif (show_origin)\n       \t\tshow_config_origin(buf);\n       \tif (show_keys)\n     -@@\n     - \tint nongit = !startup_info->have_repository;\n     - \tchar *value;\n     - \n     -+\n     -+\n     - \tgiven_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));\n     - \n     - \targc = parse_options(argc, argv, prefix, builtin_config_options,\n      @@\n       \t\t\t!strcmp(given_config_source.file, \"-\")) {\n       \t\tgiven_config_source.file = NULL;\n     @@ -286,11 +279,8 @@\n      +\tcase CONFIG_SCOPE_SUBMODULE:\n      +\t\treturn \"submodule\";\n       \tcase CONFIG_SCOPE_COMMAND:\n     --\t\treturn \"command\";\n     -+\t\treturn \"cmdline\";\n     + \t\treturn \"command\";\n       \tdefault:\n     - \t\treturn \"unknown\";\n     - \t}\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n     @@ -333,6 +323,14 @@\n      +\ttest_cmp expect output\n      +'\n      +\n     ++test_expect_success '--show-scope getting a single value' '\n     ++\tcat >expect <<-\\EOF &&\n     ++\t\tlocal\ttrue\n     ++\tEOF\n     ++\tgit config --show-scope --get user.local >output &&\n     ++\ttest_cmp expect output\n     ++'\n     ++\n      +test_expect_success '--show-scope with --show-origin' '\n      +\tcat >expect <<-EOF &&\n      +\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n\n-- \ngitgitgadget\n"},{"id":"389992","messageId":"f5a81a4d25e112a2785d081a609eddf514e91d95.1579275102.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","subject":"[PATCH v3 1/4] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-17T15:31:39Z","receivedAt":"2020-01-17T15:31:49Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"389993","messageId":"97b8a7641d1ae76b9b4766a8f96c77af1aff55f5.1579275102.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","subject":"[PATCH v3 3/4] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-17T15:31:41Z","receivedAt":"2020-01-17T15:31:49Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  Options passed in using this\nmechanism share similar scoping characteristics with the --file and\n--blob options of the 'config' command, namely that they are only in use\nfor that single invocation of git, and that they supersede the normal\nsystem/global/local hierarchy.  This patch introduces\nCONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\nCONFIG_SCOPE_CMDLINE redundant.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 2 +-\n config.h               | 2 +-\n t/helper/test-config.c | 4 ++--\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 447a013a15..f319a3d6a0 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \ndiff --git a/config.h b/config.h\nindex 284d92fb0e..f383a71404 100644\n--- a/config.h\n+++ b/config.h\n@@ -300,7 +300,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n \n enum config_scope current_config_scope(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 6695e463eb..78bbb9eb98 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\n-- \ngitgitgadget\n\n"},{"id":"389994","messageId":"61ff3c64b5bdec4aaca71caa63efc23888713315.1579275102.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","subject":"[PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-17T15:31:42Z","receivedAt":"2020-01-17T15:31:53Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n Documentation/git-config.txt | 15 ++++++----\n builtin/config.c             | 56 ++++++++++++++++++++++++++++++----\n config.c                     |  6 +++-\n config.h                     | 20 +++++++------\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       |  2 ++\n t/t1300-config.sh            | 58 ++++++++++++++++++++++++++++++++++++\n 7 files changed, 140 insertions(+), 21 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..2e47765aab 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value \n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..d5931061e8 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static const char *scope_to_string(enum config_scope scope)\n+{\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = scope_to_string(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +247,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex f319a3d6a0..035fc8fb29 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\ndiff --git a/config.h b/config.h\nindex f383a71404..91f851e925 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,10 +35,21 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n+};\n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -294,15 +305,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 78bbb9eb98..c93bee15c3 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,6 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n \tcase CONFIG_SCOPE_COMMAND:\n \t\treturn \"command\";\n \tdefault:\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..b654a6d2f9 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tuser.global=true\n+\t\tglobal\tuser.override=global\n+\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tuser.absolute=include\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\t\tlocal\tuser.relative=include\n+\t\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\t\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope getting a single value' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\ttrue\n+\tEOF\n+\tgit config --show-scope --get user.local >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\t\tlocal\tfile:.git/config\tuser.local=true\n+\t\tlocal\tfile:.git/config\tuser.override=local\n+\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\t\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"389995","messageId":"f06f9291b7c357422abad9f9cdd7425ef9e22509.1579275102.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","subject":"[PATCH v3 2/4] config: refine config scope enum","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-17T15:31:40Z","receivedAt":"2020-01-17T15:31:54Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases, but future functionality may care whether or not the config\noptions come from a worktree or from the repository's actual local\nconfig file.  For example, the planned feature to add a '--show-scope'\nto config to allow a user to see which scope listed config options come\nfrom would confuse users if it just printed 'repo' rather than 'local'\nor 'worktree' as the documentation would lead them to expect.  As well\nas the additional benefit of making the implementation look more like\nhow the documentation describes the interface.\n\nTo accomplish this we split out what was previously considered repo\nscope to be local and worktree.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 7 ++-----\n config.h               | 3 ++-\n remote.c               | 3 ++-\n t/helper/test-config.c | 4 +++-\n t/t1308-config-set.sh  | 2 +-\n upload-pack.c          | 3 ++-\n 6 files changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..447a013a15 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..284d92fb0e 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,7 +298,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n \ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..6695e463eb 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n+\tcase CONFIG_SCOPE_LOCAL:\n \t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"cmdline\";\n \tdefault:\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 7b4e1a63eb..535b2a73f7 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=cmdline\n+\tscope=command\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"390013","messageId":"xmqq1rrxertd.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"f06f9291b7c357422abad9f9cdd7425ef9e22509.1579275102.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 2/4] config: refine config scope enum","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-17T20:44:30Z","receivedAt":"2020-01-17T20:44:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> diff --git a/config.h b/config.h\n> index 91fd4c5e96..284d92fb0e 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -298,7 +298,8 @@ enum config_scope {\n>  \tCONFIG_SCOPE_UNKNOWN = 0,\n>  \tCONFIG_SCOPE_SYSTEM,\n>  \tCONFIG_SCOPE_GLOBAL,\n> -\tCONFIG_SCOPE_REPO,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n>  \tCONFIG_SCOPE_CMDLINE,\n>  };\n\nSo the gist of the change is to split REPO into two, LOCAL and\nWORKTREE.\n\nIf we can find a way to state that concisely, perhaps we can improve\n\"refine enum\" and make it more informative.\n\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 214003d5b2..6695e463eb 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"system\";\n>  \tcase CONFIG_SCOPE_GLOBAL:\n>  \t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> +\tcase CONFIG_SCOPE_LOCAL:\n>  \t\treturn \"repo\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n>  \tcase CONFIG_SCOPE_CMDLINE:\n>  \t\treturn \"cmdline\";\n>  \tdefault:\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 7b4e1a63eb..535b2a73f7 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-cmdline\n>  \torigin=command line\n>  \tname=\n> -\tscope=cmdline\n> +\tscope=command\n\nWhy???\n\n>  \tEOF\n>  \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n>  \ttest_cmp expect actual\n> diff --git a/upload-pack.c b/upload-pack.c\n> index a00d7ece6b..c53249cac1 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n>  \t\tprecomposed_unicode = git_config_bool(var, value);\n>  \t}\n>  \n> -\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n> +\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n> +\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n>  \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n>  \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n>  \t}\n"},{"id":"390018","messageId":"xmqqwo9pdchx.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"97b8a7641d1ae76b9b4766a8f96c77af1aff55f5.1579275102.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 3/4] config: clarify meaning of command line scoping","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-17T21:00:42Z","receivedAt":"2020-01-17T21:00:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\n> values passed in via the -c option.  Options passed in using this\n> mechanism share similar scoping characteristics with the --file and\n> --blob options of the 'config' command, namely that they are only in use\n> for that single invocation of git, and that they supersede the normal\n> system/global/local hierarchy.  \n\nAll of the above justifies why it makes sense to treat --file,\n--blob and \"git -c VAR=VAL\" as the same scope (i.e. it would have\nbeen a nice part of log message of the commit that introduced\nSCOPE_CMDLINE), but that is not something we need to justify\nnow---we have such a scope for one-shot settings and these three\nsources are already treated as the same class.\n\n> This patch introduces\n> CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\n> CONFIG_SCOPE_CMDLINE redundant.\n\nThe change in this commit is to rename CMDLINE to COMMAND.  That is\nwhat the proposed log message for this step must justify.\n\n\tWe internally use CONFIG_SCOPE_CMDLINE for the scope for the\n\tconfiguration variables that come from \"git -c VAR=VAL\",\n\t\"git config --file=FILE\" and \"git config --blob=BLOB\".  As\n\twe are going to expose the scope names to end-users in the\n\tnext step, let's rethink the half-cryptic \"cmdline\" and\n\tinstead use a proper word \"command\" (the settings from three\n\tsources in this scope are all in effect only during a single\n\tinvocation of a git command).\n\nor something like that.\n\n\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"repo\";\n>  \tcase CONFIG_SCOPE_WORKTREE:\n>  \t\treturn \"worktree\";\n> -\tcase CONFIG_SCOPE_CMDLINE:\n> -\t\treturn \"cmdline\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n\nThe only externally observable effect of this patch is this output\nstring from test-tool and we are not breaking end-user experience,\nbut I am not sure if this churn is worth it.  I dunno.\n\nIn any case, the change to t1308 we saw in the previous step belongs\nto this step, I think.\n"},{"id":"390021","messageId":"xmqqsgkddbjz.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"61ff3c64b5bdec4aaca71caa63efc23888713315.1579275102.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-17T21:21:04Z","receivedAt":"2020-01-17T21:21:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +--show-scope::\n> +\tSimilar to `--show-origin` in that it augments the output of\n> +\tall queried config options with the scope of that value \n> +\t(local, global, system, command).\n> +\n>  --get-colorbool name [stdout-is-tty]::\n>  \n>  \tFind the color setting for `name` (e.g. `color.diff`) and output\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 52a904cfb1..d5931061e8 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -33,6 +33,7 @@ static int end_nul;\n>  static int respect_includes_opt = -1;\n>  static struct config_options config_options;\n>  static int show_origin;\n> +static int show_scope;\n>  \n>  #define ACTION_GET (1<<0)\n>  #define ACTION_GET_ALL (1<<1)\n> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n>  \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n>  \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n>  \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n> +\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n>  \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n>  \tOPT_END(),\n>  };\n> @@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)\n>  \tstrbuf_addch(buf, term);\n>  }\n>  \n> +static const char *scope_to_string(enum config_scope scope)\n> +{\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n> +\tdefault:\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n\nIt is a shame that with this defined in the main part of the system\ntest-tool still needs to carry its own private copy.\n\nI wonder if it results in a better system if we rename this to\n\n\tconst char *config_scope_name(enum config_scope scope)\n\nmade it externally visible, and use it in t/helper/test-config.c\nand get rid of the private copy scope_name() there?\n\n> diff --git a/config.h b/config.h\n> index f383a71404..91f851e925 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -35,10 +35,21 @@ struct object_id;\n>  \n>  #define CONFIG_REGEX_NONE ((void *)1)\n>  \n> +enum config_scope {\n> +\tCONFIG_SCOPE_UNKNOWN = 0,\n> +\tCONFIG_SCOPE_SYSTEM,\n> +\tCONFIG_SCOPE_GLOBAL,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n> +\tCONFIG_SCOPE_COMMAND,\n> +\tCONFIG_SCOPE_SUBMODULE,\n> +};\n> +\n\nAnd this is the logical place to make an external definition, if we\nwere to go that route.\n\n> diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> index 983a0a1583..b654a6d2f9 100755\n> --- a/t/t1300-config.sh\n> +++ b/t/t1300-config.sh\n> @@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '\n>  \ttest_cmp expect output\n>  '\n>  \n> +test_expect_success '--show-scope with --list' '\n> +\tcat >expect <<-EOF &&\n> +\t\tglobal\tuser.global=true\n> +\t\tglobal\tuser.override=global\n> +\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\t\tglobal\tuser.absolute=include\n> +\t\tlocal\tuser.local=true\n> +\t\tlocal\tuser.override=local\n> +\t\tlocal\tinclude.path=../include/relative.include\n> +\t\tlocal\tuser.relative=include\n> +\t\tcommand\tuser.cmdline=true\n> +\tEOF\n\nThe HERE-DOC is over-indented.  All the body lines should align with\ncat and EOF.  The same comment applies to many \"<<-\" added by this\npatch---mimick the \"<<-\" that appear in earlier part of the same\nfile.\n\n> +test_expect_success !MINGW '--show-scope with --blob' '\n> +\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n> +\tcat >expect <<-EOF &&\n> +\t\tcommand\tuser.custom=true\n> +\tEOF\n> +\tgit config --blob=$blob --show-scope --list >output &&\n> +\ttest_cmp expect output\n> +'\n\nMissing blank line between two tests.\n\nI wonder if we want to revamp the tests for --show-origin that wants\nto make sure a funny filename is quoted properly.  For that purpose,\nCUSTOM_CONFIG_FILE is given a funny pathname, and it would have been\nOK to use that only for a single \"do we quote properly?\" test, but\ninstead we use that same funnily-named file as the source in many\nplaces where we do not *care* how --show-origin quotes the pathname\nat all, and end up having to skip with !MINGW.\n\nIt's a bad tradition that started at 45bf3297 (\"t1300: fix the new\n--show-origin tests on Windows\", 2016-03-23), I guess, and is not a\nnew problem introduced by this patch, but it should stop so that we\ncan have a better test coverage everywhere.\n\nOther than that, I think that the new feature added by this series\nis a sensible one.  Thanks for working on it.\n\n"},{"id":"390024","messageId":"CAKPyHN2vZbJparPNVQ1C9nOKk5ZrfeOZWxwbcLnTbwbdJWMLgA@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqsgkddbjz.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2020-01-17T21:26:48Z","receivedAt":"2020-01-17T21:27:04Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"On Fri, Jan 17, 2020 at 10:21 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > +--show-scope::\n> > +     Similar to `--show-origin` in that it augments the output of\n> > +     all queried config options with the scope of that value\n> > +     (local, global, system, command).\n> > +\n> >  --get-colorbool name [stdout-is-tty]::\n> >\n> >       Find the color setting for `name` (e.g. `color.diff`) and output\n> > diff --git a/builtin/config.c b/builtin/config.c\n> > index 52a904cfb1..d5931061e8 100644\n> > --- a/builtin/config.c\n> > +++ b/builtin/config.c\n> > @@ -33,6 +33,7 @@ static int end_nul;\n> >  static int respect_includes_opt = -1;\n> >  static struct config_options config_options;\n> >  static int show_origin;\n> > +static int show_scope;\n> >\n> >  #define ACTION_GET (1<<0)\n> >  #define ACTION_GET_ALL (1<<1)\n> > @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n> >       OPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n> >       OPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n> >       OPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n> > +     OPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n> >       OPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n> >       OPT_END(),\n> >  };\n> > @@ -189,11 +191,43 @@ static void show_config_origin(struct strbuf *buf)\n> >       strbuf_addch(buf, term);\n> >  }\n> >\n> > +static const char *scope_to_string(enum config_scope scope)\n> > +{\n> > +     switch (scope) {\n> > +     case CONFIG_SCOPE_LOCAL:\n> > +             return \"local\";\n> > +     case CONFIG_SCOPE_GLOBAL:\n> > +             return \"global\";\n> > +     case CONFIG_SCOPE_SYSTEM:\n> > +             return \"system\";\n> > +     case CONFIG_SCOPE_WORKTREE:\n> > +             return \"worktree\";\n> > +     case CONFIG_SCOPE_COMMAND:\n> > +             return \"command\";\n> > +     case CONFIG_SCOPE_SUBMODULE:\n> > +             return \"submodule\";\n> > +     default:\n> > +             return \"unknown\";\n> > +     }\n> > +}\n>\n> It is a shame that with this defined in the main part of the system\n> test-tool still needs to carry its own private copy.\n>\n> I wonder if it results in a better system if we rename this to\n>\n>         const char *config_scope_name(enum config_scope scope)\n>\n> made it externally visible, and use it in t/helper/test-config.c\n> and get rid of the private copy scope_name() there?\n>\n\n+1 and please keep the order in config_scope_name the same as in the\nenum definition. Will base my 'remote rename &\nbranch.<name>.pushRemote'  series on this then.\n\nBert\n\n> > diff --git a/config.h b/config.h\n> > index f383a71404..91f851e925 100644\n> > --- a/config.h\n> > +++ b/config.h\n> > @@ -35,10 +35,21 @@ struct object_id;\n> >\n> >  #define CONFIG_REGEX_NONE ((void *)1)\n> >\n> > +enum config_scope {\n> > +     CONFIG_SCOPE_UNKNOWN = 0,\n> > +     CONFIG_SCOPE_SYSTEM,\n> > +     CONFIG_SCOPE_GLOBAL,\n> > +     CONFIG_SCOPE_LOCAL,\n> > +     CONFIG_SCOPE_WORKTREE,\n> > +     CONFIG_SCOPE_COMMAND,\n> > +     CONFIG_SCOPE_SUBMODULE,\n> > +};\n> > +\n>\n> And this is the logical place to make an external definition, if we\n> were to go that route.\n>\n> > diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> > index 983a0a1583..b654a6d2f9 100755\n> > --- a/t/t1300-config.sh\n> > +++ b/t/t1300-config.sh\n> > @@ -1766,6 +1766,64 @@ test_expect_success !MINGW '--show-origin blob ref' '\n> >       test_cmp expect output\n> >  '\n> >\n> > +test_expect_success '--show-scope with --list' '\n> > +     cat >expect <<-EOF &&\n> > +             global  user.global=true\n> > +             global  user.override=global\n> > +             global  include.path=$INCLUDE_DIR/absolute.include\n> > +             global  user.absolute=include\n> > +             local   user.local=true\n> > +             local   user.override=local\n> > +             local   include.path=../include/relative.include\n> > +             local   user.relative=include\n> > +             command user.cmdline=true\n> > +     EOF\n>\n> The HERE-DOC is over-indented.  All the body lines should align with\n> cat and EOF.  The same comment applies to many \"<<-\" added by this\n> patch---mimick the \"<<-\" that appear in earlier part of the same\n> file.\n>\n> > +test_expect_success !MINGW '--show-scope with --blob' '\n> > +     blob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n> > +     cat >expect <<-EOF &&\n> > +             command user.custom=true\n> > +     EOF\n> > +     git config --blob=$blob --show-scope --list >output &&\n> > +     test_cmp expect output\n> > +'\n>\n> Missing blank line between two tests.\n>\n> I wonder if we want to revamp the tests for --show-origin that wants\n> to make sure a funny filename is quoted properly.  For that purpose,\n> CUSTOM_CONFIG_FILE is given a funny pathname, and it would have been\n> OK to use that only for a single \"do we quote properly?\" test, but\n> instead we use that same funnily-named file as the source in many\n> places where we do not *care* how --show-origin quotes the pathname\n> at all, and end up having to skip with !MINGW.\n>\n> It's a bad tradition that started at 45bf3297 (\"t1300: fix the new\n> --show-origin tests on Windows\", 2016-03-23), I guess, and is not a\n> new problem introduced by this patch, but it should stop so that we\n> can have a better test coverage everywhere.\n>\n> Other than that, I think that the new feature added by this series\n> is a sensible one.  Thanks for working on it.\n>\n"},{"id":"390048","messageId":"CAOjrSZsnyt5PO5n74YYC4_T4rw77dEZ49frH4Fq+bKoMBX9exg@mail.gmail.com","threadId":"52477","inReplyTo":"xmqq1rrxertd.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 2/4] config: refine config scope enum","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-18T15:27:16Z","receivedAt":"2020-01-18T15:27:31Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"> So the gist of the change is to split REPO into two, LOCAL and\n> WORKTREE.\n>\n> If we can find a way to state that concisely, perhaps we can improve\n> \"refine enum\" and make it more informative.\n>\n\nShould I just say \"split repo scope\" Or is that too on the nose?\n\n> > diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> > index 214003d5b2..6695e463eb 100644\n> > --- a/t/helper/test-config.c\n> > +++ b/t/helper/test-config.c\n> > @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n> >               return \"system\";\n> >       case CONFIG_SCOPE_GLOBAL:\n> >               return \"global\";\n> > -     case CONFIG_SCOPE_REPO:\n> > +     case CONFIG_SCOPE_LOCAL:\n> >               return \"repo\";\n> > +     case CONFIG_SCOPE_WORKTREE:\n> > +             return \"worktree\";\n> >       case CONFIG_SCOPE_CMDLINE:\n> >               return \"cmdline\";\n> >       default:\n> > diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> > index 7b4e1a63eb..535b2a73f7 100755\n> > --- a/t/t1308-config-set.sh\n> > +++ b/t/t1308-config-set.sh\n> > @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n> >       value=from-cmdline\n> >       origin=command line\n> >       name=\n> > -     scope=cmdline\n> > +     scope=command\n>\n> Why???\n\nI meant to put this change into the next series in the patch, but I\nmust have messed up, so I'll readjust that.\n\n\n-- \nMatthew Rogers\n"},{"id":"390049","messageId":"CAOjrSZvm3yNH+moCJUdmJ7S2snD8MdULuBimWrvF8vNU0PVqLg@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqwo9pdchx.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 3/4] config: clarify meaning of command line scoping","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-18T15:33:06Z","receivedAt":"2020-01-18T15:33:21Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"> we have such a scope for one-shot settings and these three\n> sources are already treated as the same class.\n>\n\nSo this isn't technically correct, as before the final patch of this series we\ntechnically don't set the current_parsing_scope for those options.  This\ndoesn't actually affect anything though, because before then nothing actually\nchecks the current_parsing_scope during such calls to git config.  As such,\nit makes sense to me to keep that part of the commit message.\n\n> > This patch introduces\n> > CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\n> > CONFIG_SCOPE_CMDLINE redundant.\n>\n> The change in this commit is to rename CMDLINE to COMMAND.  That is\n> what the proposed log message for this step must justify.\n>\n>         We internally use CONFIG_SCOPE_CMDLINE for the scope for the\n>         configuration variables that come from \"git -c VAR=VAL\",\n>         \"git config --file=FILE\" and \"git config --blob=BLOB\".  As\n>         we are going to expose the scope names to end-users in the\n>         next step, let's rethink the half-cryptic \"cmdline\" and\n>         instead use a proper word \"command\" (the settings from three\n>         sources in this scope are all in effect only during a single\n>         invocation of a git command).\n>\n> or something like that.\n\nI like this explanation much better so I'll roll that into the commit message.\n>\n>\n> > --- a/t/helper/test-config.c\n> > +++ b/t/helper/test-config.c\n> > @@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n> >               return \"repo\";\n> >       case CONFIG_SCOPE_WORKTREE:\n> >               return \"worktree\";\n> > -     case CONFIG_SCOPE_CMDLINE:\n> > -             return \"cmdline\";\n> > +     case CONFIG_SCOPE_COMMAND:\n> > +             return \"command\";\n>\n> The only externally observable effect of this patch is this output\n> string from test-tool and we are not breaking end-user experience,\n> but I am not sure if this churn is worth it.  I dunno.\n>\n> In any case, the change to t1308 we saw in the previous step belongs\n> to this step, I think.\n\nYeah, this was my bad...\n\n\n\n-- \nMatthew Rogers\n"},{"id":"390050","messageId":"CAOjrSZvFphMaJ7Yaj4pq1qp+UJixgULN7qSf8v_xKKRePgXceg@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqsgkddbjz.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 4/4] config: add '--show-scope' to print the scope of a config value","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-18T15:42:05Z","receivedAt":"2020-01-18T15:42:20Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"> The HERE-DOC is over-indented.  All the body lines should align with\n> cat and EOF.  The same comment applies to many \"<<-\" added by this\n> patch---mimick the \"<<-\" that appear in earlier part of the same\n> file.\n>\n\nI was mimicking the style of the --show-origin tests, and didn't realize this\nwas a style violation.  This is done in a few tests, so I'll add a patch\nthat just goes through the file and fixes that for the existing tests as well.\n\n\n> I wonder if we want to revamp the tests for --show-origin that wants\n> to make sure a funny filename is quoted properly.  For that purpose,\n> CUSTOM_CONFIG_FILE is given a funny pathname, and it would have been\n> OK to use that only for a single \"do we quote properly?\" test, but\n> instead we use that same funnily-named file as the source in many\n> places where we do not *care* how --show-origin quotes the pathname\n> at all, and end up having to skip with !MINGW.\n>\n> It's a bad tradition that started at 45bf3297 (\"t1300: fix the new\n> --show-origin tests on Windows\", 2016-03-23), I guess, and is not a\n> new problem introduced by this patch, but it should stop so that we\n> can have a better test coverage everywhere.\n>\n\nAgreed.\n\n> Other than that, I think that the new feature added by this series\n> is a sensible one.  Thanks for working on it.\n>\n\nYou're welcome!  And thank you for the careful review.\n\n\n-- \nMatthew Rogers\n"},{"id":"390055","messageId":"xmqqblr0d4ax.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZsnyt5PO5n74YYC4_T4rw77dEZ49frH4Fq+bKoMBX9exg@mail.gmail.com","subject":"Re: [PATCH v3 2/4] config: refine config scope enum","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-18T18:09:58Z","receivedAt":"2020-01-18T18:10:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n>> So the gist of the change is to split REPO into two, LOCAL and\n>> WORKTREE.\n>>\n>> If we can find a way to state that concisely, perhaps we can improve\n>> \"refine enum\" and make it more informative.\n>>\n>\n> Should I just say \"split repo scope\" Or is that too on the nose?\n\nYeah, I think phrasing along that line would work well.\n\n\tconfig: split repo scope to local and worktree\n\nThat's 46 chars.\n\n"},{"id":"390318","messageId":"f5a81a4d25e112a2785d081a609eddf514e91d95.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 1/6] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:01Z","receivedAt":"2020-01-24T00:21:12Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"390319","messageId":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v3.git.1579275102.gitgitgadget@gmail.com","subject":"[PATCH v4 0/6] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:00Z","receivedAt":"2020-01-24T00:21:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v3:\n\n * Cleaned up t1300\n * Expanded test coverage for t1300 to not rely as much on !MINGW by using a\n   simpler filename for most tests\n * config_scope_name is now exposed in config.h\n * cleaned up commit messages for clarity/content (again)\n\nMatthew Rogers (6):\n  config: fix typo in variable name\n  t1300: fix over-indented HERE-DOCs\n  t1300: create custom config file without special characters\n  config: split repo scope to local and worktree\n  config: clarify meaning of command line scoping\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt |  15 ++-\n builtin/config.c             |  46 +++++--\n config.c                     |  35 ++++-\n config.h                     |  20 +--\n remote.c                     |   3 +-\n submodule-config.c           |   4 +-\n t/helper/test-config.c       |  17 +--\n t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------\n t/t1308-config-set.sh        |   4 +-\n upload-pack.c                |   3 +-\n 10 files changed, 248 insertions(+), 139 deletions(-)\n\n\nbase-commit: 232378479ee6c66206d47a9be175e3a39682aea6\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v4\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v3:\n\n 1:  f5a81a4d25 = 1:  f5a81a4d25 config: fix typo in variable name\n -:  ---------- > 2:  1b42f85399 t1300: fix over-indented HERE-DOCs\n -:  ---------- > 3:  9d19794dfd t1300: create custom config file without special characters\n 2:  f06f9291b7 ! 4:  9f160e281a config: refine config scope enum\n     @@ -1,6 +1,6 @@\n      Author: Matthew Rogers <mattr94@gmail.com>\n      \n     -    config: refine config scope enum\n     +    config: split repo scope to local and worktree\n      \n          Previously when iterating through git config variables, worktree config\n          and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n     @@ -93,14 +93,14 @@\n       --- a/t/t1308-config-set.sh\n       +++ b/t/t1308-config-set.sh\n      @@\n     + \tvalue=from-repo\n     + \torigin=file\n     + \tname=.git/config\n     +-\tscope=repo\n     ++\tscope=local\n     + \n     + \tkey=foo.bar\n       \tvalue=from-cmdline\n     - \torigin=command line\n     - \tname=\n     --\tscope=cmdline\n     -+\tscope=command\n     - \tEOF\n     - \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n     - \ttest_cmp expect actual\n      \n       diff --git a/upload-pack.c b/upload-pack.c\n       --- a/upload-pack.c\n 3:  97b8a7641d ! 5:  7f00f8559d config: clarify meaning of command line scoping\n     @@ -53,3 +53,16 @@\n       \tdefault:\n       \t\treturn \"unknown\";\n       \t}\n     +\n     + diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n     + --- a/t/t1308-config-set.sh\n     + +++ b/t/t1308-config-set.sh\n     +@@\n     + \tvalue=from-cmdline\n     + \torigin=command line\n     + \tname=\n     +-\tscope=cmdline\n     ++\tscope=command\n     + \tEOF\n     + \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n     + \ttest_cmp expect actual\n 4:  61ff3c64b5 ! 6:  5549db7e39 config: add '--show-scope' to print the scope of a config value\n     @@ -76,26 +76,6 @@\n       \tstrbuf_addch(buf, term);\n       }\n       \n     -+static const char *scope_to_string(enum config_scope scope)\n     -+{\n     -+\tswitch (scope) {\n     -+\tcase CONFIG_SCOPE_LOCAL:\n     -+\t\treturn \"local\";\n     -+\tcase CONFIG_SCOPE_GLOBAL:\n     -+\t\treturn \"global\";\n     -+\tcase CONFIG_SCOPE_SYSTEM:\n     -+\t\treturn \"system\";\n     -+\tcase CONFIG_SCOPE_WORKTREE:\n     -+\t\treturn \"worktree\";\n     -+\tcase CONFIG_SCOPE_COMMAND:\n     -+\t\treturn \"command\";\n     -+\tcase CONFIG_SCOPE_SUBMODULE:\n     -+\t\treturn \"submodule\";\n     -+\tdefault:\n     -+\t\treturn \"unknown\";\n     -+\t}\n     -+}\n     -+\n      +static void show_config_scope(struct strbuf *buf)\n      +{\n      +\tconst char term = end_nul ? '\\0' : '\\t';\n     @@ -211,6 +191,33 @@\n       \t/*\n       \t * If we have a specific filename, use it. Otherwise, follow the\n       \t * regular lookup sequence.\n     +@@\n     + \t}\n     + }\n     + \n     ++const char *scope_to_string(enum config_scope scope)\n     ++{\n     ++\tswitch (scope) {\n     ++\tcase CONFIG_SCOPE_SYSTEM:\n     ++\t\treturn \"system\";\n     ++\tcase CONFIG_SCOPE_GLOBAL:\n     ++\t\treturn \"global\";\n     ++\tcase CONFIG_SCOPE_LOCAL:\n     ++\t\treturn \"local\";\n     ++\tcase CONFIG_SCOPE_WORKTREE:\n     ++\t\treturn \"worktree\";\n     ++\tcase CONFIG_SCOPE_COMMAND:\n     ++\t\treturn \"command\";\n     ++\tcase CONFIG_SCOPE_SUBMODULE:\n     ++\t\treturn \"submodule\";\n     ++\tdefault:\n     ++\t\treturn \"unknown\";\n     ++\t}\n     ++}\n     ++\n     + const char *current_config_name(void)\n     + {\n     + \tconst char *name;\n      \n       diff --git a/config.h b/config.h\n       --- a/config.h\n     @@ -228,6 +235,7 @@\n      +\tCONFIG_SCOPE_COMMAND,\n      +\tCONFIG_SCOPE_SUBMODULE,\n      +};\n     ++const char *scope_to_string(enum config_scope scope);\n      +\n       struct git_config_source {\n       \tunsigned int use_stdin:1;\n     @@ -273,14 +281,38 @@\n       --- a/t/helper/test-config.c\n       +++ b/t/helper/test-config.c\n      @@\n     - \t\treturn \"repo\";\n     - \tcase CONFIG_SCOPE_WORKTREE:\n     - \t\treturn \"worktree\";\n     -+\tcase CONFIG_SCOPE_SUBMODULE:\n     -+\t\treturn \"submodule\";\n     - \tcase CONFIG_SCOPE_COMMAND:\n     - \t\treturn \"command\";\n     - \tdefault:\n     +  *\n     +  */\n     + \n     +-static const char *scope_name(enum config_scope scope)\n     +-{\n     +-\tswitch (scope) {\n     +-\tcase CONFIG_SCOPE_SYSTEM:\n     +-\t\treturn \"system\";\n     +-\tcase CONFIG_SCOPE_GLOBAL:\n     +-\t\treturn \"global\";\n     +-\tcase CONFIG_SCOPE_LOCAL:\n     +-\t\treturn \"repo\";\n     +-\tcase CONFIG_SCOPE_WORKTREE:\n     +-\t\treturn \"worktree\";\n     +-\tcase CONFIG_SCOPE_COMMAND:\n     +-\t\treturn \"command\";\n     +-\tdefault:\n     +-\t\treturn \"unknown\";\n     +-\t}\n     +-}\n     + static int iterate_cb(const char *var, const char *value, void *data)\n     + {\n     + \tstatic int nr;\n     +@@\n     + \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n     + \tprintf(\"origin=%s\\n\", current_config_origin_type());\n     + \tprintf(\"name=%s\\n\", current_config_name());\n     +-\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n     ++\tprintf(\"scope=%s\\n\", scope_to_string(current_config_scope()));\n     + \n     + \treturn 0;\n     + }\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n     @@ -313,6 +345,7 @@\n      +\tgit config --blob=$blob --show-scope --list >output &&\n      +\ttest_cmp expect output\n      +'\n     ++\n      +test_expect_success '--show-scope with --local' '\n      +\tcat >expect <<-\\EOF &&\n      +\t\tlocal\tuser.local=true\n\n-- \ngitgitgadget\n"},{"id":"390320","messageId":"1b42f853996565ebb1304701cae6cfde8d5357b1.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 2/6] t1300: fix over-indented HERE-DOCs","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:02Z","receivedAt":"2020-01-24T00:21:15Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPrepare for the following patches by removing extraneous indents from\nHERE-DOCs used in config tests.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------\n 1 file changed, 84 insertions(+), 84 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..e8b4575758 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQr = value2\n+\t[V.A]\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.a.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQR = value2\n+\t[V.A]\n+\tQR = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.a.R\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual\n@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tR = v1\n-\t\t[K \"E\"]\n-\t\tY = v1\n-\t\t[a \"b\"]\n-\t\tc = v1\n-\t\t[d \"e\"]\n-\t\tf = v1\n+\t[V \"A\"]\n+\tR = v1\n+\t[K \"E\"]\n+\tY = v1\n+\t[a \"b\"]\n+\tc = v1\n+\t[d \"e\"]\n+\tf = v1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tQr = v2\n-\t\t[K \"E\"]\n-\t\tQy = v2\n-\t\t[a \"b\"]\n-\t\tQc = v2\n-\t\t[d \"e\"]\n-\t\tf = v1\n-\t\t[d \"E\"]\n-\t\tQf = v2\n+\t[V \"A\"]\n+\tQr = v2\n+\t[K \"E\"]\n+\tQy = v2\n+\t[a \"b\"]\n+\tQc = v2\n+\t[d \"e\"]\n+\tf = v1\n+\t[d \"E\"]\n+\tQf = v2\n \tEOF\n \t# exact match\n \tgit config -f testConfig_actual a.b.c v2 &&\n@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '\n \tINCLUDE_DIR=\"$HOME/include\" &&\n \tmkdir -p \"$INCLUDE_DIR\" &&\n \tcat >\"$INCLUDE_DIR\"/absolute.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\tabsolute = include\n+\t[user]\n+\t\tabsolute = include\n \tEOF\n \tcat >\"$INCLUDE_DIR\"/relative.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\trelative = include\n+\t[user]\n+\t\trelative = include\n \tEOF\n \tcat >\"$HOME\"/.gitconfig <<-EOF &&\n-\t\t[user]\n-\t\t\tglobal = true\n-\t\t\toverride = global\n-\t\t[include]\n-\t\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n+\t[user]\n+\t\tglobal = true\n+\t\toverride = global\n+\t[include]\n+\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n \tEOF\n \tcat >.git/config <<-\\EOF\n-\t\t[user]\n-\t\t\tlocal = true\n-\t\t\toverride = local\n-\t\t[include]\n-\t\t\tpath = ../include/relative.include\n+\t[user]\n+\t\tlocal = true\n+\t\toverride = local\n+\t[include]\n+\t\tpath = ../include/relative.include\n \tEOF\n '\n \n test_expect_success '--show-origin with --list' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global=true\n-\t\tfile:$HOME/.gitconfig\tuser.override=global\n-\t\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n-\t\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n-\t\tfile:.git/../include/relative.include\tuser.relative=include\n-\t\tcommand line:\tuser.cmdline=true\n+\tfile:$HOME/.gitconfig\tuser.global=true\n+\tfile:$HOME/.gitconfig\tuser.override=global\n+\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand line:\tuser.cmdline=true\n \tEOF\n \tgit -c user.cmdline=true config --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '\n \n test_expect_success '--show-origin with --list --null' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfigQuser.global\n-\t\ttrueQfile:$HOME/.gitconfigQuser.override\n-\t\tglobalQfile:$HOME/.gitconfigQinclude.path\n-\t\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n-\t\tincludeQfile:.git/configQuser.local\n-\t\ttrueQfile:.git/configQuser.override\n-\t\tlocalQfile:.git/configQinclude.path\n-\t\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n-\t\tincludeQcommand line:Quser.cmdline\n-\t\ttrueQ\n+\tfile:$HOME/.gitconfigQuser.global\n+\ttrueQfile:$HOME/.gitconfigQuser.override\n+\tglobalQfile:$HOME/.gitconfigQinclude.path\n+\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n+\tincludeQfile:.git/configQuser.local\n+\ttrueQfile:.git/configQuser.override\n+\tlocalQfile:.git/configQinclude.path\n+\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n+\tincludeQcommand line:Quser.cmdline\n+\ttrueQ\n \tEOF\n \tgit -c user.cmdline=true config --null --list --show-origin >output.raw &&\n \tnul_to_q <output.raw >output &&\n@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '\n \n test_expect_success '--show-origin with single file' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n \tEOF\n \tgit config --local --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '\n \n test_expect_success '--show-origin with --get-regexp' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global true\n-\t\tfile:.git/config\tuser.local true\n+\tfile:$HOME/.gitconfig\tuser.global true\n+\tfile:.git/config\tuser.local true\n \tEOF\n \tgit config --show-origin --get-regexp \"user\\.[g|l].*\" >output &&\n \ttest_cmp expect output\n@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '\n \n test_expect_success '--show-origin getting a single key' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tlocal\n+\tfile:.git/config\tlocal\n \tEOF\n \tgit config --show-origin user.override >output &&\n \ttest_cmp expect output\n@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '\n test_expect_success 'set up custom config file' '\n \tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n-\t\t[user]\n-\t\t\tcustom = true\n+\t[user]\n+\t\tcustom = true\n \tEOF\n '\n \n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '\n \n test_expect_success '--show-origin stdin' '\n \tcat >expect <<-\\EOF &&\n-\t\tstandard input:\tuser.custom=true\n+\tstandard input:\tuser.custom=true\n \tEOF\n \tgit config --file - --show-origin --list <\"$CUSTOM_CONFIG_FILE\" >output &&\n \ttest_cmp expect output\n@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '\n \n test_expect_success '--show-origin stdin with file include' '\n \tcat >\"$INCLUDE_DIR\"/stdin.include <<-EOF &&\n-\t\t[user]\n-\t\t\tstdin = include\n+\t[user]\n+\t\tstdin = include\n \tEOF\n \tcat >expect <<-EOF &&\n-\t\tfile:$INCLUDE_DIR/stdin.include\tinclude\n+\tfile:$INCLUDE_DIR/stdin.include\tinclude\n \tEOF\n \techo \"[include]path=\\\"$INCLUDE_DIR\\\"/stdin.include\" |\n \tgit config --show-origin --includes --file - user.stdin >output &&\n@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '\n test_expect_success !MINGW '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n-\t\tblob:$blob\tuser.custom=true\n+\tblob:$blob\tuser.custom=true\n \tEOF\n \tgit config --blob=$blob --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '\n \n test_expect_success !MINGW '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\t\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390321","messageId":"9d19794dfd667b3f9752f0e8118dc9eb0c8f59f1.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 3/6] t1300: create custom config file without special characters","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:03Z","receivedAt":"2020-01-24T00:21:15Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nTests that required a custom configuration file to be created previously\nused a file with non-alphanumeric characters including escaped double\nquotes.  This is not really necessary for the majority of tests\ninvolving custom config files, and decreases test coverage on systems\nthat dissallow such filenames (Windows, etc.).\n\nCreate two files, one appropriate for testing quoting and one\nappropriate for general use.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n t/t1300-config.sh | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e8b4575758..e5fb9114f6 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '\n '\n \n test_expect_success 'set up custom config file' '\n-\tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tCUSTOM_CONFIG_FILE=\"custom.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n \t[user]\n \t\tcustom = true\n \tEOF\n '\n \n+test_expect_success !MINGW 'set up custom config file with special name characters' '\n+\tWEIRDLY_NAMED_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tcp \"$CUSTOM_CONFIG_FILE\" \"$WEIRDLY_NAMED_FILE\"\n+'\n+\n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n \tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n-\tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n+\tgit config --file \"$WEIRDLY_NAMED_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n '\n \n@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob' '\n+test_expect_success '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n \tblob:$blob\tuser.custom=true\n@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob ref' '\n+test_expect_success '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:master:custom.conf\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390322","messageId":"7f00f8559d4e1c4d73bdff9136b03bdd8a53e9dd.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 5/6] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:05Z","receivedAt":"2020-01-24T00:21:16Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  Options passed in using this\nmechanism share similar scoping characteristics with the --file and\n--blob options of the 'config' command, namely that they are only in use\nfor that single invocation of git, and that they supersede the normal\nsystem/global/local hierarchy.  This patch introduces\nCONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\nCONFIG_SCOPE_CMDLINE redundant.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 2 +-\n config.h               | 2 +-\n t/helper/test-config.c | 4 ++--\n t/t1308-config-set.sh  | 2 +-\n 4 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 447a013a15..f319a3d6a0 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \ndiff --git a/config.h b/config.h\nindex 284d92fb0e..f383a71404 100644\n--- a/config.h\n+++ b/config.h\n@@ -300,7 +300,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n \n enum config_scope current_config_scope(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 6695e463eb..78bbb9eb98 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 90196e2862..fba0abe429 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=cmdline\n+\tscope=command\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n-- \ngitgitgadget\n\n"},{"id":"390323","messageId":"9f160e281a984ea7578f8fbe244adc77c6585e44.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 4/6] config: split repo scope to local and worktree","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:04Z","receivedAt":"2020-01-24T00:21:18Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases, but future functionality may care whether or not the config\noptions come from a worktree or from the repository's actual local\nconfig file.  For example, the planned feature to add a '--show-scope'\nto config to allow a user to see which scope listed config options come\nfrom would confuse users if it just printed 'repo' rather than 'local'\nor 'worktree' as the documentation would lead them to expect.  As well\nas the additional benefit of making the implementation look more like\nhow the documentation describes the interface.\n\nTo accomplish this we split out what was previously considered repo\nscope to be local and worktree.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 7 ++-----\n config.h               | 3 ++-\n remote.c               | 3 ++-\n t/helper/test-config.c | 4 +++-\n t/t1308-config-set.sh  | 2 +-\n upload-pack.c          | 3 ++-\n 6 files changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..447a013a15 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..284d92fb0e 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,7 +298,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n \ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..6695e463eb 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n+\tcase CONFIG_SCOPE_LOCAL:\n \t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"cmdline\";\n \tdefault:\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 7b4e1a63eb..90196e2862 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-repo\n \torigin=file\n \tname=.git/config\n-\tscope=repo\n+\tscope=local\n \n \tkey=foo.bar\n \tvalue=from-cmdline\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"390324","messageId":"5549db7e39bf38aa5cc42292421f4676e3073b7d.1579825267.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-24T00:21:06Z","receivedAt":"2020-01-24T00:21:20Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n Documentation/git-config.txt | 15 ++++++---\n builtin/config.c             | 36 +++++++++++++++++++---\n config.c                     | 26 +++++++++++++++-\n config.h                     | 21 +++++++------\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       | 19 +-----------\n t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n 7 files changed, 141 insertions(+), 39 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..2e47765aab 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value \n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..66d2b0d2df 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = scope_to_string(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +227,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex f319a3d6a0..469dff57b4 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\n@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)\n \t}\n }\n \n+const char *scope_to_string(enum config_scope scope)\n+{\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n const char *current_config_name(void)\n {\n \tconst char *name;\ndiff --git a/config.h b/config.h\nindex f383a71404..7b3aec0092 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,10 +35,22 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n+};\n+const char *scope_to_string(enum config_scope scope);\n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 78bbb9eb98..2e91879b2a 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -37,23 +37,6 @@\n  *\n  */\n \n-static const char *scope_name(enum config_scope scope)\n-{\n-\tswitch (scope) {\n-\tcase CONFIG_SCOPE_SYSTEM:\n-\t\treturn \"system\";\n-\tcase CONFIG_SCOPE_GLOBAL:\n-\t\treturn \"global\";\n-\tcase CONFIG_SCOPE_LOCAL:\n-\t\treturn \"repo\";\n-\tcase CONFIG_SCOPE_WORKTREE:\n-\t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_COMMAND:\n-\t\treturn \"command\";\n-\tdefault:\n-\t\treturn \"unknown\";\n-\t}\n-}\n static int iterate_cb(const char *var, const char *value, void *data)\n {\n \tstatic int nr;\n@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n \tprintf(\"origin=%s\\n\", current_config_origin_type());\n \tprintf(\"name=%s\\n\", current_config_name());\n-\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n+\tprintf(\"scope=%s\\n\", scope_to_string(current_config_scope()));\n \n \treturn 0;\n }\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e5fb9114f6..79dbea9bd1 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tuser.global=true\n+\t\tglobal\tuser.override=global\n+\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tuser.absolute=include\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\t\tlocal\tuser.relative=include\n+\t\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\t\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope getting a single value' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\ttrue\n+\tEOF\n+\tgit config --show-scope --get user.local >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\t\tlocal\tfile:.git/config\tuser.local=true\n+\t\tlocal\tfile:.git/config\tuser.override=local\n+\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\t\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"390376","messageId":"xmqqblqs1yqm.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"1b42f853996565ebb1304701cae6cfde8d5357b1.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 2/6] t1300: fix over-indented HERE-DOCs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T18:43:45Z","receivedAt":"2020-01-24T18:43:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Prepare for the following patches by removing extraneous indents from\n> HERE-DOCs used in config tests.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------\n>  1 file changed, 84 insertions(+), 84 deletions(-)\n\nThis step is new.  It makes sense, I think.\n\nThanks.\n"},{"id":"390378","messageId":"xmqq5zh01ynn.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"9d19794dfd667b3f9752f0e8118dc9eb0c8f59f1.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 3/6] t1300: create custom config file without special characters","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T18:45:32Z","receivedAt":"2020-01-24T18:45:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Tests that required a custom configuration file to be created previously\n> used a file with non-alphanumeric characters including escaped double\n> quotes.  This is not really necessary for the majority of tests\n> involving custom config files, and decreases test coverage on systems\n> that dissallow such filenames (Windows, etc.).\n>\n> Create two files, one appropriate for testing quoting and one\n> appropriate for general use.\n\nNicely done.\n\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  t/t1300-config.sh | 15 ++++++++++-----\n>  1 file changed, 10 insertions(+), 5 deletions(-)\n>\n> diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> index e8b4575758..e5fb9114f6 100755\n> --- a/t/t1300-config.sh\n> +++ b/t/t1300-config.sh\n> @@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '\n>  '\n>  \n>  test_expect_success 'set up custom config file' '\n> -\tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n> +\tCUSTOM_CONFIG_FILE=\"custom.conf\" &&\n>  \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n>  \t[user]\n>  \t\tcustom = true\n>  \tEOF\n>  '\n>  \n> +test_expect_success !MINGW 'set up custom config file with special name characters' '\n> +\tWEIRDLY_NAMED_FILE=\"file\\\" (dq) and spaces.conf\" &&\n> +\tcp \"$CUSTOM_CONFIG_FILE\" \"$WEIRDLY_NAMED_FILE\"\n> +'\n\nOK.\n\n>  test_expect_success !MINGW '--show-origin escape special file name characters' '\n>  \tcat >expect <<-\\EOF &&\n>  \tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n>  \tEOF\n> -\tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n> +\tgit config --file \"$WEIRDLY_NAMED_FILE\" --show-origin --list >output &&\n>  \ttest_cmp expect output\n>  '\n>  \n> @@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '\n>  \ttest_cmp expect output\n>  '\n>  \n> -test_expect_success !MINGW '--show-origin blob' '\n> +test_expect_success '--show-origin blob' '\n>  \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n>  \tcat >expect <<-EOF &&\n>  \tblob:$blob\tuser.custom=true\n> @@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '\n>  \ttest_cmp expect output\n>  '\n>  \n> -test_expect_success !MINGW '--show-origin blob ref' '\n> +test_expect_success '--show-origin blob ref' '\n>  \tcat >expect <<-\\EOF &&\n> -\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n> +\tblob:master:custom.conf\tuser.custom=true\n>  \tEOF\n>  \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n>  \tgit commit -m \"new config file\" &&\n\nNice to see these cleaned up.\n"},{"id":"390379","messageId":"xmqq1rro1ygk.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"9f160e281a984ea7578f8fbe244adc77c6585e44.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 4/6] config: split repo scope to local and worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T18:49:47Z","receivedAt":"2020-01-24T18:49:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Previously when iterating through git config variables, worktree config\n> and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n> never a problem before as no one had needed to differentiate between the\n> two cases, but future functionality may care whether or not the config\n> options come from a worktree or from the repository's actual local\n> config file.  For example, the planned feature to add a '--show-scope'\n> to config to allow a user to see which scope listed config options come\n> from would confuse users if it just printed 'repo' rather than 'local'\n> or 'worktree' as the documentation would lead them to expect.  As well\n> as the additional benefit of making the implementation look more like\n> how the documentation describes the interface.\n>\n> To accomplish this we split out what was previously considered repo\n> scope to be local and worktree.\n>\n> The clients of 'current_config_scope()' who cared about\n> CONFIG_SCOPE_REPO are also modified to similarly care about\n> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  config.c               | 7 ++-----\n>  config.h               | 3 ++-\n>  remote.c               | 3 ++-\n>  t/helper/test-config.c | 4 +++-\n>  t/t1308-config-set.sh  | 2 +-\n>  upload-pack.c          | 3 ++-\n>  6 files changed, 12 insertions(+), 10 deletions(-)\n\nNicely done.\n\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 7b4e1a63eb..90196e2862 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-repo\n>  \torigin=file\n>  \tname=.git/config\n> -\tscope=repo\n> +\tscope=local\n>  \n>  \tkey=foo.bar\n>  \tvalue=from-cmdline\n\nOK.\n\n"},{"id":"390381","messageId":"xmqqwo9gzn60.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"9f160e281a984ea7578f8fbe244adc77c6585e44.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 4/6] config: split repo scope to local and worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T19:09:43Z","receivedAt":"2020-01-24T19:09:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 214003d5b2..6695e463eb 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"system\";\n>  \tcase CONFIG_SCOPE_GLOBAL:\n>  \t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> +\tcase CONFIG_SCOPE_LOCAL:\n>  \t\treturn \"repo\";\n\nThis must be updated to \"local\", no, to match the change to t1308?\n\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n>  \tcase CONFIG_SCOPE_CMDLINE:\n>  \t\treturn \"cmdline\";\n>  \tdefault:\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 7b4e1a63eb..90196e2862 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-repo\n>  \torigin=file\n>  \tname=.git/config\n> -\tscope=repo\n> +\tscope=local\n\n"},{"id":"390382","messageId":"xmqqsgk4zmrs.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"5549db7e39bf38aa5cc42292421f4676e3073b7d.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T19:18:15Z","receivedAt":"2020-01-24T19:18:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +const char *scope_to_string(enum config_scope scope)\n> +{\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n\nDespite the screw-up at an earlier step, this one is correct ;-)\n\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n> +\tdefault:\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n> +\n\n> diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> index e5fb9114f6..79dbea9bd1 100755\n> --- a/t/t1300-config.sh\n> +++ b/t/t1300-config.sh\n> @@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n>  \ttest_cmp expect output\n>  '\n>  \n> +test_expect_success '--show-scope with --list' '\n> +\tcat >expect <<-EOF &&\n> +\t\tglobal\tuser.global=true\n> +\t\tglobal\tuser.override=global\n> +\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\t\tglobal\tuser.absolute=include\n> +\t\tlocal\tuser.local=true\n> +\t\tlocal\tuser.override=local\n> +\t\tlocal\tinclude.path=../include/relative.include\n> +\t\tlocal\tuser.relative=include\n> +\t\tcommand\tuser.cmdline=true\n> +\tEOF\n\nWe cleaned up the existing ones that are overly indented from this\nscript in an earlier step.  Let's not re-introduce them.\n\n"},{"id":"390383","messageId":"xmqqo8uszmkj.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 0/6] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T19:22:36Z","receivedAt":"2020-01-24T19:22:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This was originally a pull request to the git-for-windows repository\n> [https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n> --show-scope which would allow a user to see what scope a given\n> configuration value has (sytem, local, global, etc.).\n\nThese generally look very good.\n\nI'll queue them with proposed fix-ups, so please do not waste your\ntime by reworking on your patches in response to my review comments\nbefore fetching today's integration result from the public\nrepository, which probably will happen in 5 hours or so.\n\nThanks.\n"},{"id":"390388","messageId":"xmqqblqszjs9.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"5549db7e39bf38aa5cc42292421f4676e3073b7d.1579825267.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-24T20:22:46Z","receivedAt":"2020-01-24T20:22:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +const char *scope_to_string(enum config_scope scope)\n> +{\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n> +\tdefault:\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n\nIn earlier round(s), this was called config_scope_name(), wasn't it?\n\n\"scope_to_string()\" is a much worse than \"config_scope_name()\" as a\nname of a global function (e.g. we won't know what subsystems other\nthan \"config\" may want to use \"scope\").  As you remember, Bert's\n\"remote rename\" series wants to use a public interface like this\nfunction, and the series expects this function to be called\nconfig_scope_name().  Let's not rename a public API function\nsuddenly---it disrupts other topics in flight.\n\nThanks.\n"},{"id":"390391","messageId":"CAOjrSZsTZic1daj7zG1tZbgENUxt7XGU3mTJAC4_gdiybFMt0Q@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqblqszjs9.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-24T20:49:38Z","receivedAt":"2020-01-24T20:49:52Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"I think this was a mess-up on my end.  I had meant to rename it to\nconfig_scope_name() (after talking with Bert) but it appears that I\nhad messed up, so I think my mistake wasn't to rename the function, but\nto fail to rename it.  So I do apologize.\n\nOn Fri, Jan 24, 2020 at 3:22 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n> > +const char *scope_to_string(enum config_scope scope)\n> > +{\n> > +     switch (scope) {\n> > +     case CONFIG_SCOPE_SYSTEM:\n> > +             return \"system\";\n> > +     case CONFIG_SCOPE_GLOBAL:\n> > +             return \"global\";\n> > +     case CONFIG_SCOPE_LOCAL:\n> > +             return \"local\";\n> > +     case CONFIG_SCOPE_WORKTREE:\n> > +             return \"worktree\";\n> > +     case CONFIG_SCOPE_COMMAND:\n> > +             return \"command\";\n> > +     case CONFIG_SCOPE_SUBMODULE:\n> > +             return \"submodule\";\n> > +     default:\n> > +             return \"unknown\";\n> > +     }\n> > +}\n>\n> In earlier round(s), this was called config_scope_name(), wasn't it?\n>\n> \"scope_to_string()\" is a much worse than \"config_scope_name()\" as a\n> name of a global function (e.g. we won't know what subsystems other\n> than \"config\" may want to use \"scope\").  As you remember, Bert's\n> \"remote rename\" series wants to use a public interface like this\n> function, and the series expects this function to be called\n> config_scope_name().  Let's not rename a public API function\n> suddenly---it disrupts other topics in flight.\n>\n> Thanks.\n\n\n\n-- \nMatthew Rogers\n"},{"id":"390430","messageId":"xmqq8slwcs62.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZsTZic1daj7zG1tZbgENUxt7XGU3mTJAC4_gdiybFMt0Q@mail.gmail.com","subject":"Re: [PATCH v4 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-25T00:10:13Z","receivedAt":"2020-01-25T00:10:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n> I think this was a mess-up on my end.  I had meant to rename it to\n> config_scope_name() (after talking with Bert) but it appears that I\n> had messed up, so I think my mistake wasn't to rename the function, but\n> to fail to rename it.  So I do apologize.\n\nNo need to.  I just wanted to make sure everybody involved is aware\nof what others are doing to avoid wasted effort.\n\nNow I do expect the (hopefully) final reroll of your topic, so that\nBert can fork his topic on top of it.\n\nThanks.\n"},{"id":"390436","messageId":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v4.git.1579825267.gitgitgadget@gmail.com","subject":"[PATCH v5 0/6] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:18Z","receivedAt":"2020-01-25T00:39:29Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v3:\n\n * Cleaned up t1300\n * Expanded test coverage for t1300 to not rely as much on !MINGW by using a\n   simpler filename for most tests\n * config_scope_name is now exposed in config.h\n * cleaned up commit messages for clarity/content (again)\n\nMatthew Rogers (6):\n  config: fix typo in variable name\n  t1300: fix over-indented HERE-DOCs\n  t1300: create custom config file without special characters\n  config: split repo scope to local and worktree\n  config: clarify meaning of command line scoping\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt |  15 ++-\n builtin/config.c             |  46 +++++--\n config.c                     |  35 ++++-\n config.h                     |  20 +--\n remote.c                     |   3 +-\n submodule-config.c           |   4 +-\n t/helper/test-config.c       |  17 +--\n t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------\n t/t1308-config-set.sh        |   4 +-\n upload-pack.c                |   3 +-\n 10 files changed, 248 insertions(+), 139 deletions(-)\n\n\nbase-commit: 232378479ee6c66206d47a9be175e3a39682aea6\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v5\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v4:\n\n 1:  f5a81a4d25 = 1:  f5a81a4d25 config: fix typo in variable name\n 2:  1b42f85399 = 2:  1b42f85399 t1300: fix over-indented HERE-DOCs\n 3:  9d19794dfd = 3:  9d19794dfd t1300: create custom config file without special characters\n 4:  9f160e281a = 4:  9f160e281a config: split repo scope to local and worktree\n 5:  7f00f8559d = 5:  7f00f8559d config: clarify meaning of command line scoping\n 6:  5549db7e39 = 6:  2e979d9fa5 config: add '--show-scope' to print the scope of a config value\n\n-- \ngitgitgadget\n"},{"id":"390437","messageId":"f5a81a4d25e112a2785d081a609eddf514e91d95.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 1/6] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:19Z","receivedAt":"2020-01-25T00:39:29Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"390438","messageId":"9d19794dfd667b3f9752f0e8118dc9eb0c8f59f1.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 3/6] t1300: create custom config file without special characters","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:21Z","receivedAt":"2020-01-25T00:39:33Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nTests that required a custom configuration file to be created previously\nused a file with non-alphanumeric characters including escaped double\nquotes.  This is not really necessary for the majority of tests\ninvolving custom config files, and decreases test coverage on systems\nthat dissallow such filenames (Windows, etc.).\n\nCreate two files, one appropriate for testing quoting and one\nappropriate for general use.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n t/t1300-config.sh | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e8b4575758..e5fb9114f6 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '\n '\n \n test_expect_success 'set up custom config file' '\n-\tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tCUSTOM_CONFIG_FILE=\"custom.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n \t[user]\n \t\tcustom = true\n \tEOF\n '\n \n+test_expect_success !MINGW 'set up custom config file with special name characters' '\n+\tWEIRDLY_NAMED_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tcp \"$CUSTOM_CONFIG_FILE\" \"$WEIRDLY_NAMED_FILE\"\n+'\n+\n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n \tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n-\tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n+\tgit config --file \"$WEIRDLY_NAMED_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n '\n \n@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob' '\n+test_expect_success '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n \tblob:$blob\tuser.custom=true\n@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob ref' '\n+test_expect_success '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:master:custom.conf\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390439","messageId":"1b42f853996565ebb1304701cae6cfde8d5357b1.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 2/6] t1300: fix over-indented HERE-DOCs","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:20Z","receivedAt":"2020-01-25T00:39:33Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPrepare for the following patches by removing extraneous indents from\nHERE-DOCs used in config tests.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------\n 1 file changed, 84 insertions(+), 84 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..e8b4575758 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQr = value2\n+\t[V.A]\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.a.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQR = value2\n+\t[V.A]\n+\tQR = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.a.R\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual\n@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tR = v1\n-\t\t[K \"E\"]\n-\t\tY = v1\n-\t\t[a \"b\"]\n-\t\tc = v1\n-\t\t[d \"e\"]\n-\t\tf = v1\n+\t[V \"A\"]\n+\tR = v1\n+\t[K \"E\"]\n+\tY = v1\n+\t[a \"b\"]\n+\tc = v1\n+\t[d \"e\"]\n+\tf = v1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tQr = v2\n-\t\t[K \"E\"]\n-\t\tQy = v2\n-\t\t[a \"b\"]\n-\t\tQc = v2\n-\t\t[d \"e\"]\n-\t\tf = v1\n-\t\t[d \"E\"]\n-\t\tQf = v2\n+\t[V \"A\"]\n+\tQr = v2\n+\t[K \"E\"]\n+\tQy = v2\n+\t[a \"b\"]\n+\tQc = v2\n+\t[d \"e\"]\n+\tf = v1\n+\t[d \"E\"]\n+\tQf = v2\n \tEOF\n \t# exact match\n \tgit config -f testConfig_actual a.b.c v2 &&\n@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '\n \tINCLUDE_DIR=\"$HOME/include\" &&\n \tmkdir -p \"$INCLUDE_DIR\" &&\n \tcat >\"$INCLUDE_DIR\"/absolute.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\tabsolute = include\n+\t[user]\n+\t\tabsolute = include\n \tEOF\n \tcat >\"$INCLUDE_DIR\"/relative.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\trelative = include\n+\t[user]\n+\t\trelative = include\n \tEOF\n \tcat >\"$HOME\"/.gitconfig <<-EOF &&\n-\t\t[user]\n-\t\t\tglobal = true\n-\t\t\toverride = global\n-\t\t[include]\n-\t\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n+\t[user]\n+\t\tglobal = true\n+\t\toverride = global\n+\t[include]\n+\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n \tEOF\n \tcat >.git/config <<-\\EOF\n-\t\t[user]\n-\t\t\tlocal = true\n-\t\t\toverride = local\n-\t\t[include]\n-\t\t\tpath = ../include/relative.include\n+\t[user]\n+\t\tlocal = true\n+\t\toverride = local\n+\t[include]\n+\t\tpath = ../include/relative.include\n \tEOF\n '\n \n test_expect_success '--show-origin with --list' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global=true\n-\t\tfile:$HOME/.gitconfig\tuser.override=global\n-\t\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n-\t\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n-\t\tfile:.git/../include/relative.include\tuser.relative=include\n-\t\tcommand line:\tuser.cmdline=true\n+\tfile:$HOME/.gitconfig\tuser.global=true\n+\tfile:$HOME/.gitconfig\tuser.override=global\n+\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand line:\tuser.cmdline=true\n \tEOF\n \tgit -c user.cmdline=true config --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '\n \n test_expect_success '--show-origin with --list --null' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfigQuser.global\n-\t\ttrueQfile:$HOME/.gitconfigQuser.override\n-\t\tglobalQfile:$HOME/.gitconfigQinclude.path\n-\t\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n-\t\tincludeQfile:.git/configQuser.local\n-\t\ttrueQfile:.git/configQuser.override\n-\t\tlocalQfile:.git/configQinclude.path\n-\t\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n-\t\tincludeQcommand line:Quser.cmdline\n-\t\ttrueQ\n+\tfile:$HOME/.gitconfigQuser.global\n+\ttrueQfile:$HOME/.gitconfigQuser.override\n+\tglobalQfile:$HOME/.gitconfigQinclude.path\n+\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n+\tincludeQfile:.git/configQuser.local\n+\ttrueQfile:.git/configQuser.override\n+\tlocalQfile:.git/configQinclude.path\n+\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n+\tincludeQcommand line:Quser.cmdline\n+\ttrueQ\n \tEOF\n \tgit -c user.cmdline=true config --null --list --show-origin >output.raw &&\n \tnul_to_q <output.raw >output &&\n@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '\n \n test_expect_success '--show-origin with single file' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n \tEOF\n \tgit config --local --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '\n \n test_expect_success '--show-origin with --get-regexp' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global true\n-\t\tfile:.git/config\tuser.local true\n+\tfile:$HOME/.gitconfig\tuser.global true\n+\tfile:.git/config\tuser.local true\n \tEOF\n \tgit config --show-origin --get-regexp \"user\\.[g|l].*\" >output &&\n \ttest_cmp expect output\n@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '\n \n test_expect_success '--show-origin getting a single key' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tlocal\n+\tfile:.git/config\tlocal\n \tEOF\n \tgit config --show-origin user.override >output &&\n \ttest_cmp expect output\n@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '\n test_expect_success 'set up custom config file' '\n \tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n-\t\t[user]\n-\t\t\tcustom = true\n+\t[user]\n+\t\tcustom = true\n \tEOF\n '\n \n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '\n \n test_expect_success '--show-origin stdin' '\n \tcat >expect <<-\\EOF &&\n-\t\tstandard input:\tuser.custom=true\n+\tstandard input:\tuser.custom=true\n \tEOF\n \tgit config --file - --show-origin --list <\"$CUSTOM_CONFIG_FILE\" >output &&\n \ttest_cmp expect output\n@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '\n \n test_expect_success '--show-origin stdin with file include' '\n \tcat >\"$INCLUDE_DIR\"/stdin.include <<-EOF &&\n-\t\t[user]\n-\t\t\tstdin = include\n+\t[user]\n+\t\tstdin = include\n \tEOF\n \tcat >expect <<-EOF &&\n-\t\tfile:$INCLUDE_DIR/stdin.include\tinclude\n+\tfile:$INCLUDE_DIR/stdin.include\tinclude\n \tEOF\n \techo \"[include]path=\\\"$INCLUDE_DIR\\\"/stdin.include\" |\n \tgit config --show-origin --includes --file - user.stdin >output &&\n@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '\n test_expect_success !MINGW '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n-\t\tblob:$blob\tuser.custom=true\n+\tblob:$blob\tuser.custom=true\n \tEOF\n \tgit config --blob=$blob --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '\n \n test_expect_success !MINGW '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\t\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390440","messageId":"7f00f8559d4e1c4d73bdff9136b03bdd8a53e9dd.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 5/6] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:23Z","receivedAt":"2020-01-25T00:39:33Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  Options passed in using this\nmechanism share similar scoping characteristics with the --file and\n--blob options of the 'config' command, namely that they are only in use\nfor that single invocation of git, and that they supersede the normal\nsystem/global/local hierarchy.  This patch introduces\nCONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\nCONFIG_SCOPE_CMDLINE redundant.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 2 +-\n config.h               | 2 +-\n t/helper/test-config.c | 4 ++--\n t/t1308-config-set.sh  | 2 +-\n 4 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 447a013a15..f319a3d6a0 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \ndiff --git a/config.h b/config.h\nindex 284d92fb0e..f383a71404 100644\n--- a/config.h\n+++ b/config.h\n@@ -300,7 +300,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n \n enum config_scope current_config_scope(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 6695e463eb..78bbb9eb98 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 90196e2862..fba0abe429 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=cmdline\n+\tscope=command\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n-- \ngitgitgadget\n\n"},{"id":"390441","messageId":"9f160e281a984ea7578f8fbe244adc77c6585e44.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 4/6] config: split repo scope to local and worktree","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:22Z","receivedAt":"2020-01-25T00:39:36Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases, but future functionality may care whether or not the config\noptions come from a worktree or from the repository's actual local\nconfig file.  For example, the planned feature to add a '--show-scope'\nto config to allow a user to see which scope listed config options come\nfrom would confuse users if it just printed 'repo' rather than 'local'\nor 'worktree' as the documentation would lead them to expect.  As well\nas the additional benefit of making the implementation look more like\nhow the documentation describes the interface.\n\nTo accomplish this we split out what was previously considered repo\nscope to be local and worktree.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 7 ++-----\n config.h               | 3 ++-\n remote.c               | 3 ++-\n t/helper/test-config.c | 4 +++-\n t/t1308-config-set.sh  | 2 +-\n upload-pack.c          | 3 ++-\n 6 files changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..447a013a15 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..284d92fb0e 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,7 +298,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n \ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..6695e463eb 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n+\tcase CONFIG_SCOPE_LOCAL:\n \t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"cmdline\";\n \tdefault:\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 7b4e1a63eb..90196e2862 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-repo\n \torigin=file\n \tname=.git/config\n-\tscope=repo\n+\tscope=local\n \n \tkey=foo.bar\n \tvalue=from-cmdline\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"390442","messageId":"2e979d9fa5066f61eb89e3c1a1a34ac813d71700.1579912764.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-25T00:39:24Z","receivedAt":"2020-01-25T00:39:37Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n Documentation/git-config.txt | 15 ++++++---\n builtin/config.c             | 36 +++++++++++++++++++---\n config.c                     | 26 +++++++++++++++-\n config.h                     | 21 +++++++------\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       | 19 +-----------\n t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n 7 files changed, 141 insertions(+), 39 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..2e47765aab 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value \n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..66d2b0d2df 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = scope_to_string(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +227,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex f319a3d6a0..469dff57b4 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\n@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)\n \t}\n }\n \n+const char *scope_to_string(enum config_scope scope)\n+{\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n const char *current_config_name(void)\n {\n \tconst char *name;\ndiff --git a/config.h b/config.h\nindex f383a71404..7b3aec0092 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,10 +35,22 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n+};\n+const char *scope_to_string(enum config_scope scope);\n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 78bbb9eb98..2e91879b2a 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -37,23 +37,6 @@\n  *\n  */\n \n-static const char *scope_name(enum config_scope scope)\n-{\n-\tswitch (scope) {\n-\tcase CONFIG_SCOPE_SYSTEM:\n-\t\treturn \"system\";\n-\tcase CONFIG_SCOPE_GLOBAL:\n-\t\treturn \"global\";\n-\tcase CONFIG_SCOPE_LOCAL:\n-\t\treturn \"repo\";\n-\tcase CONFIG_SCOPE_WORKTREE:\n-\t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_COMMAND:\n-\t\treturn \"command\";\n-\tdefault:\n-\t\treturn \"unknown\";\n-\t}\n-}\n static int iterate_cb(const char *var, const char *value, void *data)\n {\n \tstatic int nr;\n@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n \tprintf(\"origin=%s\\n\", current_config_origin_type());\n \tprintf(\"name=%s\\n\", current_config_name());\n-\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n+\tprintf(\"scope=%s\\n\", scope_to_string(current_config_scope()));\n \n \treturn 0;\n }\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e5fb9114f6..79dbea9bd1 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tuser.global=true\n+\t\tglobal\tuser.override=global\n+\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tuser.absolute=include\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\t\tlocal\tuser.relative=include\n+\t\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\t\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\tuser.local=true\n+\t\tlocal\tuser.override=local\n+\t\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope getting a single value' '\n+\tcat >expect <<-\\EOF &&\n+\t\tlocal\ttrue\n+\tEOF\n+\tgit config --show-scope --get user.local >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\t\tlocal\tfile:.git/config\tuser.local=true\n+\t\tlocal\tfile:.git/config\tuser.override=local\n+\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\t\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"390591","messageId":"xmqqblqoa43u.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"9f160e281a984ea7578f8fbe244adc77c6585e44.1579912764.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v5 4/6] config: split repo scope to local and worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-27T23:09:41Z","receivedAt":"2020-01-27T23:09:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 214003d5b2..6695e463eb 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n>  \t\treturn \"system\";\n>  \tcase CONFIG_SCOPE_GLOBAL:\n>  \t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> +\tcase CONFIG_SCOPE_LOCAL:\n>  \t\treturn \"repo\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n\nIt used to be only \"repo\"; now we give either \"repo\" or \"worktree\".\n\n>  \tcase CONFIG_SCOPE_CMDLINE:\n>  \t\treturn \"cmdline\";\n>  \tdefault:\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 7b4e1a63eb..90196e2862 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-repo\n>  \torigin=file\n>  \tname=.git/config\n> -\tscope=repo\n> +\tscope=local\n\nBut the test expects \"local\".\n\nThis patch cannot be correct.  I recall fixing this manually when I\nqueued the previous round to 'pu'.  Please double check.\n"},{"id":"390594","messageId":"xmqq7e1ca3ze.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"2e979d9fa5066f61eb89e3c1a1a34ac813d71700.1579912764.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-27T23:12:21Z","receivedAt":"2020-01-27T23:12:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> When a user queries config values with --show-origin, often it's\n> difficult to determine what the actual \"scope\" (local, global, etc.) of\n> a given value is based on just the origin file.\n>\n> Teach 'git config' the '--show-scope' option to print the scope of all\n> displayed config values.  Note that we should never see anything of\n> \"submodule\" scope as that is only ever used by submodule-config.c when\n> parsing the '.gitmodules' file.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  Documentation/git-config.txt | 15 ++++++---\n>  builtin/config.c             | 36 +++++++++++++++++++---\n>  config.c                     | 26 +++++++++++++++-\n>  config.h                     | 21 +++++++------\n>  submodule-config.c           |  4 ++-\n>  t/helper/test-config.c       | 19 +-----------\n>  t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n>  7 files changed, 141 insertions(+), 39 deletions(-)\n>\n> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n> index 899e92a1c9..2e47765aab 100644\n> --- a/Documentation/git-config.txt\n> +++ b/Documentation/git-config.txt\n> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n>  SYNOPSIS\n>  --------\n>  [verse]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n>  'git config' [<file-option>] [--type=<type>] --add name value\n>  'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n>  'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n>  'git config' [<file-option>] --unset name [value_regex]\n>  'git config' [<file-option>] --unset-all name [value_regex]\n>  'git config' [<file-option>] --rename-section old_name new_name\n>  'git config' [<file-option>] --remove-section name\n> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n> +'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n>  'git config' [<file-option>] --get-color name [default]\n>  'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n>  'git config' [<file-option>] -e | --edit\n> @@ -222,6 +222,11 @@ Valid `<type>`'s include:\n>  \tthe actual origin (config file path, ref, or blob id if\n>  \tapplicable).\n>  \n> +--show-scope::\n> +\tSimilar to `--show-origin` in that it augments the output of\n> +\tall queried config options with the scope of that value \n\nThere is a trailing SP on this line.  I think I fixed it up when I\nqueued the last round on 'pu'.  Please double check.\n\n> +\tconst char *scope = scope_to_string(current_config_scope());\n\n???  Are we using scope_to_string() back again?\n\nI thought I queued a fix-up patch when I queued the last round on\n'pu' to unblock the other topic that wanted to build on top.  Please\ndouble check.\n\nThanks.\n"},{"id":"390601","messageId":"CAOjrSZs9xdS9sLVA912UtWOz_dRnOjAn4UZ7SCyAJi95-0A4dA@mail.gmail.com","threadId":"52477","inReplyTo":"xmqq7e1ca3ze.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-28T01:31:05Z","receivedAt":"2020-01-28T01:31:20Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":">\n> There is a trailing SP on this line.  I think I fixed it up when I\n> queued the last round on 'pu'.  Please double check.\n>\n> > +     const char *scope = scope_to_string(current_config_scope());\n>\n> ???  Are we using scope_to_string() back again?\n>\n> I thought I queued a fix-up patch when I queued the last round on\n> 'pu' to unblock the other topic that wanted to build on top.  Please\n> double check.\n>\n> Thanks.\n\nI think I messed up when I pulled those changes...\n\nI can get it all sorted out tomorrow after work\n\n-- \nMatthew Rogers\n"},{"id":"390685","messageId":"18f92f70cf249a246dfc128dec093c8cd95e2f00.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 1/6] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:20Z","receivedAt":"2020-01-29T03:34:31Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"390686","messageId":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v5.git.1579912764.gitgitgadget@gmail.com","subject":"[PATCH v6 0/6] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:19Z","receivedAt":"2020-01-29T03:34:31Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v4:\n\n * final cleanups\n\nMatthew Rogers (6):\n  config: fix typo in variable name\n  t1300: fix over-indented HERE-DOCs\n  t1300: create custom config file without special characters\n  config: split repo scope to local and worktree\n  config: clarify meaning of command line scoping\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt |  15 ++-\n builtin/config.c             |  46 +++++--\n config.c                     |  35 ++++-\n config.h                     |  20 +--\n remote.c                     |   3 +-\n submodule-config.c           |   4 +-\n t/helper/test-config.c       |  17 +--\n t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------\n t/t1308-config-set.sh        |   4 +-\n upload-pack.c                |   3 +-\n 10 files changed, 248 insertions(+), 139 deletions(-)\n\n\nbase-commit: c7a62075917b3340f908093f63f1161c44ed1475\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v6\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v6\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v5:\n\n 1:  f5a81a4d25 ! 1:  18f92f70cf config: fix typo in variable name\n     @@ -8,6 +8,7 @@\n          malapropism is being fixed.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/builtin/config.c b/builtin/config.c\n       --- a/builtin/config.c\n 2:  1b42f85399 ! 2:  dc7b3f3b96 t1300: fix over-indented HERE-DOCs\n     @@ -6,6 +6,7 @@\n          HERE-DOCs used in config tests.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n 3:  9d19794dfd ! 3:  975e652368 t1300: create custom config file without special characters\n     @@ -12,6 +12,7 @@\n          appropriate for general use.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n 4:  9f160e281a ! 4:  1e406ba430 config: split repo scope to local and worktree\n     @@ -22,6 +22,7 @@\n          CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/config.c b/config.c\n       --- a/config.c\n     @@ -81,8 +82,9 @@\n       \tcase CONFIG_SCOPE_GLOBAL:\n       \t\treturn \"global\";\n      -\tcase CONFIG_SCOPE_REPO:\n     +-\t\treturn \"repo\";\n      +\tcase CONFIG_SCOPE_LOCAL:\n     - \t\treturn \"repo\";\n     ++\t\treturn \"local\";\n      +\tcase CONFIG_SCOPE_WORKTREE:\n      +\t\treturn \"worktree\";\n       \tcase CONFIG_SCOPE_CMDLINE:\n 5:  7f00f8559d ! 5:  936ce91c62 config: clarify meaning of command line scoping\n     @@ -12,6 +12,7 @@\n          CONFIG_SCOPE_CMDLINE redundant.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/config.c b/config.c\n       --- a/config.c\n     @@ -43,7 +44,7 @@\n       --- a/t/helper/test-config.c\n       +++ b/t/helper/test-config.c\n      @@\n     - \t\treturn \"repo\";\n     + \t\treturn \"local\";\n       \tcase CONFIG_SCOPE_WORKTREE:\n       \t\treturn \"worktree\";\n      -\tcase CONFIG_SCOPE_CMDLINE:\n 6:  2e979d9fa5 ! 6:  fc141e8689 config: add '--show-scope' to print the scope of a config value\n     @@ -12,6 +12,7 @@\n          parsing the '.gitmodules' file.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     +    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n       --- a/Documentation/git-config.txt\n     @@ -46,7 +47,7 @@\n       \n      +--show-scope::\n      +\tSimilar to `--show-origin` in that it augments the output of\n     -+\tall queried config options with the scope of that value \n     ++\tall queried config options with the scope of that value\n      +\t(local, global, system, command).\n      +\n       --get-colorbool name [stdout-is-tty]::\n     @@ -79,7 +80,7 @@\n      +static void show_config_scope(struct strbuf *buf)\n      +{\n      +\tconst char term = end_nul ? '\\0' : '\\t';\n     -+\tconst char *scope = scope_to_string(current_config_scope());\n     ++\tconst char *scope = config_scope_name(current_config_scope());\n      +\n      +\tstrbuf_addstr(buf, N_(scope));\n      +\tstrbuf_addch(buf, term);\n     @@ -195,7 +196,7 @@\n       \t}\n       }\n       \n     -+const char *scope_to_string(enum config_scope scope)\n     ++const char *config_scope_name(enum config_scope scope)\n      +{\n      +\tswitch (scope) {\n      +\tcase CONFIG_SCOPE_SYSTEM:\n     @@ -235,7 +236,7 @@\n      +\tCONFIG_SCOPE_COMMAND,\n      +\tCONFIG_SCOPE_SUBMODULE,\n      +};\n     -+const char *scope_to_string(enum config_scope scope);\n     ++const char *config_scope_name(enum config_scope scope);\n      +\n       struct git_config_source {\n       \tunsigned int use_stdin:1;\n     @@ -292,7 +293,7 @@\n      -\tcase CONFIG_SCOPE_GLOBAL:\n      -\t\treturn \"global\";\n      -\tcase CONFIG_SCOPE_LOCAL:\n     --\t\treturn \"repo\";\n     +-\t\treturn \"local\";\n      -\tcase CONFIG_SCOPE_WORKTREE:\n      -\t\treturn \"worktree\";\n      -\tcase CONFIG_SCOPE_COMMAND:\n     @@ -309,7 +310,7 @@\n       \tprintf(\"origin=%s\\n\", current_config_origin_type());\n       \tprintf(\"name=%s\\n\", current_config_name());\n      -\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n     -+\tprintf(\"scope=%s\\n\", scope_to_string(current_config_scope()));\n     ++\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n       \n       \treturn 0;\n       }\n     @@ -323,15 +324,15 @@\n       \n      +test_expect_success '--show-scope with --list' '\n      +\tcat >expect <<-EOF &&\n     -+\t\tglobal\tuser.global=true\n     -+\t\tglobal\tuser.override=global\n     -+\t\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n     -+\t\tglobal\tuser.absolute=include\n     -+\t\tlocal\tuser.local=true\n     -+\t\tlocal\tuser.override=local\n     -+\t\tlocal\tinclude.path=../include/relative.include\n     -+\t\tlocal\tuser.relative=include\n     -+\t\tcommand\tuser.cmdline=true\n     ++\tglobal\tuser.global=true\n     ++\tglobal\tuser.override=global\n     ++\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n     ++\tglobal\tuser.absolute=include\n     ++\tlocal\tuser.local=true\n     ++\tlocal\tuser.override=local\n     ++\tlocal\tinclude.path=../include/relative.include\n     ++\tlocal\tuser.relative=include\n     ++\tcommand\tuser.cmdline=true\n      +\tEOF\n      +\tgit -c user.cmdline=true config --list --show-scope >output &&\n      +\ttest_cmp expect output\n     @@ -340,7 +341,7 @@\n      +test_expect_success !MINGW '--show-scope with --blob' '\n      +\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n      +\tcat >expect <<-EOF &&\n     -+\t\tcommand\tuser.custom=true\n     ++\tcommand\tuser.custom=true\n      +\tEOF\n      +\tgit config --blob=$blob --show-scope --list >output &&\n      +\ttest_cmp expect output\n     @@ -348,9 +349,9 @@\n      +\n      +test_expect_success '--show-scope with --local' '\n      +\tcat >expect <<-\\EOF &&\n     -+\t\tlocal\tuser.local=true\n     -+\t\tlocal\tuser.override=local\n     -+\t\tlocal\tinclude.path=../include/relative.include\n     ++\tlocal\tuser.local=true\n     ++\tlocal\tuser.override=local\n     ++\tlocal\tinclude.path=../include/relative.include\n      +\tEOF\n      +\tgit config --local --list --show-scope >output &&\n      +\ttest_cmp expect output\n     @@ -358,7 +359,7 @@\n      +\n      +test_expect_success '--show-scope getting a single value' '\n      +\tcat >expect <<-\\EOF &&\n     -+\t\tlocal\ttrue\n     ++\tlocal\ttrue\n      +\tEOF\n      +\tgit config --show-scope --get user.local >output &&\n      +\ttest_cmp expect output\n     @@ -366,15 +367,15 @@\n      +\n      +test_expect_success '--show-scope with --show-origin' '\n      +\tcat >expect <<-EOF &&\n     -+\t\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n     -+\t\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n     -+\t\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n     -+\t\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n     -+\t\tlocal\tfile:.git/config\tuser.local=true\n     -+\t\tlocal\tfile:.git/config\tuser.override=local\n     -+\t\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n     -+\t\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n     -+\t\tcommand\tcommand line:\tuser.cmdline=true\n     ++\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n     ++\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n     ++\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n     ++\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n     ++\tlocal\tfile:.git/config\tuser.local=true\n     ++\tlocal\tfile:.git/config\tuser.override=local\n     ++\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n     ++\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n     ++\tcommand\tcommand line:\tuser.cmdline=true\n      +\tEOF\n      +\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n      +\ttest_cmp expect output\n\n-- \ngitgitgadget\n"},{"id":"390687","messageId":"975e65236890eff3fdbf0af5664903bf3ea6962d.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 3/6] t1300: create custom config file without special characters","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:22Z","receivedAt":"2020-01-29T03:34:34Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nTests that required a custom configuration file to be created previously\nused a file with non-alphanumeric characters including escaped double\nquotes.  This is not really necessary for the majority of tests\ninvolving custom config files, and decreases test coverage on systems\nthat dissallow such filenames (Windows, etc.).\n\nCreate two files, one appropriate for testing quoting and one\nappropriate for general use.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1300-config.sh | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e8b4575758..e5fb9114f6 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '\n '\n \n test_expect_success 'set up custom config file' '\n-\tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tCUSTOM_CONFIG_FILE=\"custom.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n \t[user]\n \t\tcustom = true\n \tEOF\n '\n \n+test_expect_success !MINGW 'set up custom config file with special name characters' '\n+\tWEIRDLY_NAMED_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tcp \"$CUSTOM_CONFIG_FILE\" \"$WEIRDLY_NAMED_FILE\"\n+'\n+\n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n \tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n-\tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n+\tgit config --file \"$WEIRDLY_NAMED_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n '\n \n@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob' '\n+test_expect_success '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n \tblob:$blob\tuser.custom=true\n@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob ref' '\n+test_expect_success '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:master:custom.conf\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390688","messageId":"dc7b3f3b96da5978ca69af0f3bd1aedeb012f76b.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 2/6] t1300: fix over-indented HERE-DOCs","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:21Z","receivedAt":"2020-01-29T03:34:34Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPrepare for the following patches by removing extraneous indents from\nHERE-DOCs used in config tests.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------\n 1 file changed, 84 insertions(+), 84 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..e8b4575758 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQr = value2\n+\t[V.A]\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.a.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQR = value2\n+\t[V.A]\n+\tQR = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.a.R\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual\n@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tR = v1\n-\t\t[K \"E\"]\n-\t\tY = v1\n-\t\t[a \"b\"]\n-\t\tc = v1\n-\t\t[d \"e\"]\n-\t\tf = v1\n+\t[V \"A\"]\n+\tR = v1\n+\t[K \"E\"]\n+\tY = v1\n+\t[a \"b\"]\n+\tc = v1\n+\t[d \"e\"]\n+\tf = v1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tQr = v2\n-\t\t[K \"E\"]\n-\t\tQy = v2\n-\t\t[a \"b\"]\n-\t\tQc = v2\n-\t\t[d \"e\"]\n-\t\tf = v1\n-\t\t[d \"E\"]\n-\t\tQf = v2\n+\t[V \"A\"]\n+\tQr = v2\n+\t[K \"E\"]\n+\tQy = v2\n+\t[a \"b\"]\n+\tQc = v2\n+\t[d \"e\"]\n+\tf = v1\n+\t[d \"E\"]\n+\tQf = v2\n \tEOF\n \t# exact match\n \tgit config -f testConfig_actual a.b.c v2 &&\n@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '\n \tINCLUDE_DIR=\"$HOME/include\" &&\n \tmkdir -p \"$INCLUDE_DIR\" &&\n \tcat >\"$INCLUDE_DIR\"/absolute.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\tabsolute = include\n+\t[user]\n+\t\tabsolute = include\n \tEOF\n \tcat >\"$INCLUDE_DIR\"/relative.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\trelative = include\n+\t[user]\n+\t\trelative = include\n \tEOF\n \tcat >\"$HOME\"/.gitconfig <<-EOF &&\n-\t\t[user]\n-\t\t\tglobal = true\n-\t\t\toverride = global\n-\t\t[include]\n-\t\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n+\t[user]\n+\t\tglobal = true\n+\t\toverride = global\n+\t[include]\n+\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n \tEOF\n \tcat >.git/config <<-\\EOF\n-\t\t[user]\n-\t\t\tlocal = true\n-\t\t\toverride = local\n-\t\t[include]\n-\t\t\tpath = ../include/relative.include\n+\t[user]\n+\t\tlocal = true\n+\t\toverride = local\n+\t[include]\n+\t\tpath = ../include/relative.include\n \tEOF\n '\n \n test_expect_success '--show-origin with --list' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global=true\n-\t\tfile:$HOME/.gitconfig\tuser.override=global\n-\t\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n-\t\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n-\t\tfile:.git/../include/relative.include\tuser.relative=include\n-\t\tcommand line:\tuser.cmdline=true\n+\tfile:$HOME/.gitconfig\tuser.global=true\n+\tfile:$HOME/.gitconfig\tuser.override=global\n+\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand line:\tuser.cmdline=true\n \tEOF\n \tgit -c user.cmdline=true config --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '\n \n test_expect_success '--show-origin with --list --null' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfigQuser.global\n-\t\ttrueQfile:$HOME/.gitconfigQuser.override\n-\t\tglobalQfile:$HOME/.gitconfigQinclude.path\n-\t\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n-\t\tincludeQfile:.git/configQuser.local\n-\t\ttrueQfile:.git/configQuser.override\n-\t\tlocalQfile:.git/configQinclude.path\n-\t\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n-\t\tincludeQcommand line:Quser.cmdline\n-\t\ttrueQ\n+\tfile:$HOME/.gitconfigQuser.global\n+\ttrueQfile:$HOME/.gitconfigQuser.override\n+\tglobalQfile:$HOME/.gitconfigQinclude.path\n+\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n+\tincludeQfile:.git/configQuser.local\n+\ttrueQfile:.git/configQuser.override\n+\tlocalQfile:.git/configQinclude.path\n+\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n+\tincludeQcommand line:Quser.cmdline\n+\ttrueQ\n \tEOF\n \tgit -c user.cmdline=true config --null --list --show-origin >output.raw &&\n \tnul_to_q <output.raw >output &&\n@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '\n \n test_expect_success '--show-origin with single file' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n \tEOF\n \tgit config --local --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '\n \n test_expect_success '--show-origin with --get-regexp' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global true\n-\t\tfile:.git/config\tuser.local true\n+\tfile:$HOME/.gitconfig\tuser.global true\n+\tfile:.git/config\tuser.local true\n \tEOF\n \tgit config --show-origin --get-regexp \"user\\.[g|l].*\" >output &&\n \ttest_cmp expect output\n@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '\n \n test_expect_success '--show-origin getting a single key' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tlocal\n+\tfile:.git/config\tlocal\n \tEOF\n \tgit config --show-origin user.override >output &&\n \ttest_cmp expect output\n@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '\n test_expect_success 'set up custom config file' '\n \tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n-\t\t[user]\n-\t\t\tcustom = true\n+\t[user]\n+\t\tcustom = true\n \tEOF\n '\n \n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '\n \n test_expect_success '--show-origin stdin' '\n \tcat >expect <<-\\EOF &&\n-\t\tstandard input:\tuser.custom=true\n+\tstandard input:\tuser.custom=true\n \tEOF\n \tgit config --file - --show-origin --list <\"$CUSTOM_CONFIG_FILE\" >output &&\n \ttest_cmp expect output\n@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '\n \n test_expect_success '--show-origin stdin with file include' '\n \tcat >\"$INCLUDE_DIR\"/stdin.include <<-EOF &&\n-\t\t[user]\n-\t\t\tstdin = include\n+\t[user]\n+\t\tstdin = include\n \tEOF\n \tcat >expect <<-EOF &&\n-\t\tfile:$INCLUDE_DIR/stdin.include\tinclude\n+\tfile:$INCLUDE_DIR/stdin.include\tinclude\n \tEOF\n \techo \"[include]path=\\\"$INCLUDE_DIR\\\"/stdin.include\" |\n \tgit config --show-origin --includes --file - user.stdin >output &&\n@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '\n test_expect_success !MINGW '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n-\t\tblob:$blob\tuser.custom=true\n+\tblob:$blob\tuser.custom=true\n \tEOF\n \tgit config --blob=$blob --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '\n \n test_expect_success !MINGW '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\t\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"390689","messageId":"936ce91c628d018791e7cd74ad60d74ea3f5491e.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 5/6] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:24Z","receivedAt":"2020-01-29T03:34:36Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  Options passed in using this\nmechanism share similar scoping characteristics with the --file and\n--blob options of the 'config' command, namely that they are only in use\nfor that single invocation of git, and that they supersede the normal\nsystem/global/local hierarchy.  This patch introduces\nCONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\nCONFIG_SCOPE_CMDLINE redundant.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n config.c               | 2 +-\n config.h               | 2 +-\n t/helper/test-config.c | 4 ++--\n t/t1308-config-set.sh  | 2 +-\n 4 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 447a013a15..f319a3d6a0 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \ndiff --git a/config.h b/config.h\nindex 284d92fb0e..f383a71404 100644\n--- a/config.h\n+++ b/config.h\n@@ -300,7 +300,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n \n enum config_scope current_config_scope(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 9c6ae7a8a7..56c1f6dfb6 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"local\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 90196e2862..fba0abe429 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=cmdline\n+\tscope=command\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n-- \ngitgitgadget\n\n"},{"id":"390690","messageId":"1e406ba43093405c1675024ff4bf8ca66737a202.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 4/6] config: split repo scope to local and worktree","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:23Z","receivedAt":"2020-01-29T03:34:37Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases, but future functionality may care whether or not the config\noptions come from a worktree or from the repository's actual local\nconfig file.  For example, the planned feature to add a '--show-scope'\nto config to allow a user to see which scope listed config options come\nfrom would confuse users if it just printed 'repo' rather than 'local'\nor 'worktree' as the documentation would lead them to expect.  As well\nas the additional benefit of making the implementation look more like\nhow the documentation describes the interface.\n\nTo accomplish this we split out what was previously considered repo\nscope to be local and worktree.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n config.c               | 7 ++-----\n config.h               | 3 ++-\n remote.c               | 3 ++-\n t/helper/test-config.c | 6 ++++--\n t/t1308-config-set.sh  | 2 +-\n upload-pack.c          | 3 ++-\n 6 files changed, 13 insertions(+), 11 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..447a013a15 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..284d92fb0e 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,7 +298,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n \ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..9c6ae7a8a7 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n-\t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"cmdline\";\n \tdefault:\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 7b4e1a63eb..90196e2862 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-repo\n \torigin=file\n \tname=.git/config\n-\tscope=repo\n+\tscope=local\n \n \tkey=foo.bar\n \tvalue=from-cmdline\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"390691","messageId":"fc141e86896edb4241e84cc300e191889a3fa4ea.1580268865.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-01-29T03:34:25Z","receivedAt":"2020-01-29T03:34:39Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-config.txt | 15 ++++++---\n builtin/config.c             | 36 +++++++++++++++++++---\n config.c                     | 26 +++++++++++++++-\n config.h                     | 21 +++++++------\n submodule-config.c           |  4 ++-\n t/helper/test-config.c       | 19 +-----------\n t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n 7 files changed, 141 insertions(+), 39 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..7573160f21 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value\n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..ee4aef6a35 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = config_scope_name(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +227,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\n@@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex f319a3d6a0..18a6bdd9ff 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\n@@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)\n \t}\n }\n \n+const char *config_scope_name(enum config_scope scope)\n+{\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n const char *current_config_name(void)\n {\n \tconst char *name;\ndiff --git a/config.h b/config.h\nindex f383a71404..fe0addb0dc 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,10 +35,22 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n+};\n+const char *config_scope_name(enum config_scope scope);\n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -294,15 +306,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 56c1f6dfb6..1e3bc7c8f4 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -37,23 +37,6 @@\n  *\n  */\n \n-static const char *scope_name(enum config_scope scope)\n-{\n-\tswitch (scope) {\n-\tcase CONFIG_SCOPE_SYSTEM:\n-\t\treturn \"system\";\n-\tcase CONFIG_SCOPE_GLOBAL:\n-\t\treturn \"global\";\n-\tcase CONFIG_SCOPE_LOCAL:\n-\t\treturn \"local\";\n-\tcase CONFIG_SCOPE_WORKTREE:\n-\t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_COMMAND:\n-\t\treturn \"command\";\n-\tdefault:\n-\t\treturn \"unknown\";\n-\t}\n-}\n static int iterate_cb(const char *var, const char *value, void *data)\n {\n \tstatic int nr;\n@@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n \tprintf(\"origin=%s\\n\", current_config_origin_type());\n \tprintf(\"name=%s\\n\", current_config_name());\n-\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n+\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n \n \treturn 0;\n }\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e5fb9114f6..5464c46c18 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\tglobal\tuser.global=true\n+\tglobal\tuser.override=global\n+\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tglobal\tuser.absolute=include\n+\tlocal\tuser.local=true\n+\tlocal\tuser.override=local\n+\tlocal\tinclude.path=../include/relative.include\n+\tlocal\tuser.relative=include\n+\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\tlocal\tuser.local=true\n+\tlocal\tuser.override=local\n+\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope getting a single value' '\n+\tcat >expect <<-\\EOF &&\n+\tlocal\ttrue\n+\tEOF\n+\tgit config --show-scope --get user.local >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tlocal\tfile:.git/config\tuser.local=true\n+\tlocal\tfile:.git/config\tuser.override=local\n+\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"390698","messageId":"xmqqzhe66dav.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"Re: [PATCH v6 0/6] config: allow user to know scope of config options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-01-29T05:29:12Z","receivedAt":"2020-01-29T05:29:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This was originally a pull request to the git-for-windows repository\n> [https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n> --show-scope which would allow a user to see what scope a given\n> configuration value has (sytem, local, global, etc.).\n>\n> changes since v4:\n>\n>  * final cleanups\n\nIndeed.  This round looks good.\n\nThanks.\n"},{"id":"390704","messageId":"8ede2f21-46a8-b95f-6425-c0ee54abdad6@googlemail.com","threadId":"52477","inReplyTo":"fc141e86896edb4241e84cc300e191889a3fa4ea.1580268865.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2020-01-29T09:08:04Z","receivedAt":"2020-01-29T09:08:14Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"Dear Matthew,\n\nOn 29.01.20 04:34, Matthew Rogers via GitGitGadget wrote:\n> From: Matthew Rogers <mattr94@gmail.com>\n> \n> When a user queries config values with --show-origin, often it's\n> difficult to determine what the actual \"scope\" (local, global, etc.) of\n> a given value is based on just the origin file.\n> \n> Teach 'git config' the '--show-scope' option to print the scope of all\n> displayed config values.  Note that we should never see anything of\n> \"submodule\" scope as that is only ever used by submodule-config.c when\n> parsing the '.gitmodules' file.\n> \n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>   Documentation/git-config.txt | 15 ++++++---\n>   builtin/config.c             | 36 +++++++++++++++++++---\n>   config.c                     | 26 +++++++++++++++-\n>   config.h                     | 21 +++++++------\n>   submodule-config.c           |  4 ++-\n>   t/helper/test-config.c       | 19 +-----------\n>   t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n>   7 files changed, 141 insertions(+), 39 deletions(-)\n\nfor clarity, I think this patch should be split up further.\n\nFor example:\n\n  - moving an enum and adding a new entry should be avoided\n  - does the changes to '/config.c' fix something?\n  - exposing config_scope_name should have been done before PATCH 4/6 already\n\nBest,\nBert\n\n> \n> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n> index 899e92a1c9..7573160f21 100644\n> --- a/Documentation/git-config.txt\n> +++ b/Documentation/git-config.txt\n> @@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n>   SYNOPSIS\n>   --------\n>   [verse]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n>   'git config' [<file-option>] [--type=<type>] --add name value\n>   'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n> -'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n> +'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n>   'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n>   'git config' [<file-option>] --unset name [value_regex]\n>   'git config' [<file-option>] --unset-all name [value_regex]\n>   'git config' [<file-option>] --rename-section old_name new_name\n>   'git config' [<file-option>] --remove-section name\n> -'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n> +'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n>   'git config' [<file-option>] --get-color name [default]\n>   'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n>   'git config' [<file-option>] -e | --edit\n> @@ -222,6 +222,11 @@ Valid `<type>`'s include:\n>   \tthe actual origin (config file path, ref, or blob id if\n>   \tapplicable).\n>   \n> +--show-scope::\n> +\tSimilar to `--show-origin` in that it augments the output of\n> +\tall queried config options with the scope of that value\n> +\t(local, global, system, command).\n> +\n>   --get-colorbool name [stdout-is-tty]::\n>   \n>   \tFind the color setting for `name` (e.g. `color.diff`) and output\n> diff --git a/builtin/config.c b/builtin/config.c\n> index 52a904cfb1..ee4aef6a35 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -33,6 +33,7 @@ static int end_nul;\n>   static int respect_includes_opt = -1;\n>   static struct config_options config_options;\n>   static int show_origin;\n> +static int show_scope;\n>   \n>   #define ACTION_GET (1<<0)\n>   #define ACTION_GET_ALL (1<<1)\n> @@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n>   \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n>   \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n>   \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n> +\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n>   \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n>   \tOPT_END(),\n>   };\n> @@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)\n>   \tstrbuf_addch(buf, term);\n>   }\n>   \n> +static void show_config_scope(struct strbuf *buf)\n> +{\n> +\tconst char term = end_nul ? '\\0' : '\\t';\n> +\tconst char *scope = config_scope_name(current_config_scope());\n> +\n> +\tstrbuf_addstr(buf, N_(scope));\n> +\tstrbuf_addch(buf, term);\n> +}\n> +\n>   static int show_all_config(const char *key_, const char *value_, void *cb)\n>   {\n> -\tif (show_origin) {\n> +\tif (show_origin || show_scope) {\n>   \t\tstruct strbuf buf = STRBUF_INIT;\n> -\t\tshow_config_origin(&buf);\n> +\t\tif (show_scope)\n> +\t\t\tshow_config_scope(&buf);\n> +\t\tif (show_origin)\n> +\t\t\tshow_config_origin(&buf);\n>   \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n>   \t\tfwrite(buf.buf, 1, buf.len, stdout);\n>   \t\tstrbuf_release(&buf);\n> @@ -213,6 +227,8 @@ struct strbuf_list {\n>   \n>   static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n>   {\n> +\tif (show_scope)\n> +\t\tshow_config_scope(buf);\n>   \tif (show_origin)\n>   \t\tshow_config_origin(buf);\n>   \tif (show_keys)\n> @@ -622,6 +638,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>   \t\t\t!strcmp(given_config_source.file, \"-\")) {\n>   \t\tgiven_config_source.file = NULL;\n>   \t\tgiven_config_source.use_stdin = 1;\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n>   \t}\n>   \n>   \tif (use_global_config) {\n> @@ -637,6 +654,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>   \t\t\t */\n>   \t\t\tdie(_(\"$HOME not set\"));\n>   \n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n> +\n>   \t\tif (access_or_warn(user_config, R_OK, 0) &&\n>   \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n>   \t\t\tgiven_config_source.file = xdg_config;\n> @@ -646,11 +665,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>   \t\t\tfree(xdg_config);\n>   \t\t}\n>   \t}\n> -\telse if (use_system_config)\n> +\telse if (use_system_config) {\n>   \t\tgiven_config_source.file = git_etc_gitconfig();\n> -\telse if (use_local_config)\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n> +\t} else if (use_local_config) {\n>   \t\tgiven_config_source.file = git_pathdup(\"config\");\n> -\telse if (use_worktree_config) {\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n> +\t} else if (use_worktree_config) {\n>   \t\tstruct worktree **worktrees = get_worktrees(0);\n>   \t\tif (repository_format_worktree_config)\n>   \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n> @@ -662,13 +683,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n>   \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n>   \t\telse\n>   \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n>   \t\tfree_worktrees(worktrees);\n>   \t} else if (given_config_source.file) {\n>   \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n>   \t\t\tgiven_config_source.file =\n>   \t\t\t\tprefix_filename(prefix, given_config_source.file);\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n> +\t} else if (given_config_source.blob) {\n> +\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n>   \t}\n>   \n> +\n>   \tif (respect_includes_opt == -1)\n>   \t\tconfig_options.respect_includes = !given_config_source.file;\n>   \telse\n> diff --git a/config.c b/config.c\n> index f319a3d6a0..18a6bdd9ff 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>   \tchar *xdg_config = xdg_config_home(\"config\");\n>   \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n>   \tchar *repo_config;\n> +\tenum config_scope prev_parsing_scope = current_parsing_scope;\n>   \n>   \tif (opts->commondir)\n>   \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>   \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n>   \t\tdie(_(\"unable to parse command-line config\"));\n>   \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n> +\tcurrent_parsing_scope = prev_parsing_scope;\n>   \tfree(xdg_config);\n>   \tfree(user_config);\n>   \tfree(repo_config);\n> @@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n>   \t\tdata = &inc;\n>   \t}\n>   \n> +\tif (config_source)\n> +\t\tcurrent_parsing_scope = config_source->scope;\n> +\n>   \t/*\n>   \t * If we have a specific filename, use it. Otherwise, follow the\n>   \t * regular lookup sequence.\n> @@ -3294,6 +3298,26 @@ const char *current_config_origin_type(void)\n>   \t}\n>   }\n>   \n> +const char *config_scope_name(enum config_scope scope)\n> +{\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n> +\tdefault:\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n> +\n>   const char *current_config_name(void)\n>   {\n>   \tconst char *name;\n> diff --git a/config.h b/config.h\n> index f383a71404..fe0addb0dc 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -35,10 +35,22 @@ struct object_id;\n>   \n>   #define CONFIG_REGEX_NONE ((void *)1)\n>   \n> +enum config_scope {\n> +\tCONFIG_SCOPE_UNKNOWN = 0,\n> +\tCONFIG_SCOPE_SYSTEM,\n> +\tCONFIG_SCOPE_GLOBAL,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n> +\tCONFIG_SCOPE_COMMAND,\n> +\tCONFIG_SCOPE_SUBMODULE,\n> +};\n> +const char *config_scope_name(enum config_scope scope);\n> +\n>   struct git_config_source {\n>   \tunsigned int use_stdin:1;\n>   \tconst char *file;\n>   \tconst char *blob;\n> +\tenum config_scope scope;\n>   };\n>   \n>   enum config_origin_type {\n> @@ -294,15 +306,6 @@ int config_error_nonbool(const char *);\n>   \n>   int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n>   \n> -enum config_scope {\n> -\tCONFIG_SCOPE_UNKNOWN = 0,\n> -\tCONFIG_SCOPE_SYSTEM,\n> -\tCONFIG_SCOPE_GLOBAL,\n> -\tCONFIG_SCOPE_LOCAL,\n> -\tCONFIG_SCOPE_WORKTREE,\n> -\tCONFIG_SCOPE_COMMAND,\n> -};\n> -\n>   enum config_scope current_config_scope(void);\n>   const char *current_config_origin_type(void);\n>   const char *current_config_name(void);\n> diff --git a/submodule-config.c b/submodule-config.c\n> index 85064810b2..b8e97d8ae8 100644\n> --- a/submodule-config.c\n> +++ b/submodule-config.c\n> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n>   static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n>   {\n>   \tif (repo->worktree) {\n> -\t\tstruct git_config_source config_source = { 0 };\n> +\t\tstruct git_config_source config_source = {\n> +\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n> +\t\t};\n>   \t\tconst struct config_options opts = { 0 };\n>   \t\tstruct object_id oid;\n>   \t\tchar *file;\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 56c1f6dfb6..1e3bc7c8f4 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -37,23 +37,6 @@\n>    *\n>    */\n>   \n> -static const char *scope_name(enum config_scope scope)\n> -{\n> -\tswitch (scope) {\n> -\tcase CONFIG_SCOPE_SYSTEM:\n> -\t\treturn \"system\";\n> -\tcase CONFIG_SCOPE_GLOBAL:\n> -\t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_LOCAL:\n> -\t\treturn \"local\";\n> -\tcase CONFIG_SCOPE_WORKTREE:\n> -\t\treturn \"worktree\";\n> -\tcase CONFIG_SCOPE_COMMAND:\n> -\t\treturn \"command\";\n> -\tdefault:\n> -\t\treturn \"unknown\";\n> -\t}\n> -}\n>   static int iterate_cb(const char *var, const char *value, void *data)\n>   {\n>   \tstatic int nr;\n> @@ -65,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n>   \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n>   \tprintf(\"origin=%s\\n\", current_config_origin_type());\n>   \tprintf(\"name=%s\\n\", current_config_name());\n> -\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n> +\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n>   \n>   \treturn 0;\n>   }\n> diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n> index e5fb9114f6..5464c46c18 100755\n> --- a/t/t1300-config.sh\n> +++ b/t/t1300-config.sh\n> @@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n>   \ttest_cmp expect output\n>   '\n>   \n> +test_expect_success '--show-scope with --list' '\n> +\tcat >expect <<-EOF &&\n> +\tglobal\tuser.global=true\n> +\tglobal\tuser.override=global\n> +\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\tglobal\tuser.absolute=include\n> +\tlocal\tuser.local=true\n> +\tlocal\tuser.override=local\n> +\tlocal\tinclude.path=../include/relative.include\n> +\tlocal\tuser.relative=include\n> +\tcommand\tuser.cmdline=true\n> +\tEOF\n> +\tgit -c user.cmdline=true config --list --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success !MINGW '--show-scope with --blob' '\n> +\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n> +\tcat >expect <<-EOF &&\n> +\tcommand\tuser.custom=true\n> +\tEOF\n> +\tgit config --blob=$blob --show-scope --list >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success '--show-scope with --local' '\n> +\tcat >expect <<-\\EOF &&\n> +\tlocal\tuser.local=true\n> +\tlocal\tuser.override=local\n> +\tlocal\tinclude.path=../include/relative.include\n> +\tEOF\n> +\tgit config --local --list --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success '--show-scope getting a single value' '\n> +\tcat >expect <<-\\EOF &&\n> +\tlocal\ttrue\n> +\tEOF\n> +\tgit config --show-scope --get user.local >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n> +test_expect_success '--show-scope with --show-origin' '\n> +\tcat >expect <<-EOF &&\n> +\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n> +\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n> +\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n> +\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n> +\tlocal\tfile:.git/config\tuser.local=true\n> +\tlocal\tfile:.git/config\tuser.override=local\n> +\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n> +\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n> +\tcommand\tcommand line:\tuser.cmdline=true\n> +\tEOF\n> +\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n> +\ttest_cmp expect output\n> +'\n> +\n>   test_expect_success '--local requires a repo' '\n>   \t# we expect 128 to ensure that we do not simply\n>   \t# fail to find anything and return code \"1\"\n> \n"},{"id":"390758","messageId":"CAOjrSZtx+Qr4HsaptaxseTa_8oCwRyVE+Jf95_z51fGmXBjsTQ@mail.gmail.com","threadId":"52477","inReplyTo":"8ede2f21-46a8-b95f-6425-c0ee54abdad6@googlemail.com","subject":"Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-01-29T23:03:34Z","receivedAt":"2020-01-29T23:03:48Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":">\n> for clarity, I think this patch should be split up further.\n>\n> For example:\n>\n>   - moving an enum and adding a new entry should be avoided\n\nAs far as adding a new entry, that could probably be done in a separate patch.\nThe submodule scoping is correct (mostly so config options that come from\nsubmodule blobs have a sane value to set the new scope field of\ngit_config_source), but moving it is unavoidable as I'd either have to move\nconfig_scope or git_config_source for this patch to work, and moving\ngit_config_source seemed like a ton more work\n\n>   - does the changes to '/config.c' fix something?\n\nAnother thing, that in hindsight could probably be split out. The other changes\ndo fix the fact that previously recursive calls to do_git_config_sequence()\nwould blow awway the current_parsing_scope information for higher level callers.\nThis is not super common, but does occur when --show-scope is used with the\n--blob option.\n\n>   - exposing config_scope_name should have been done before PATCH 4/6 already\n\nIf that's better/more convenient, I don't have a problem breaking that\nout and moving\nit there.\n\n\n-- \nMatthew Rogers\n"},{"id":"391184","messageId":"xmqqr1z86eqb.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZtx+Qr4HsaptaxseTa_8oCwRyVE+Jf95_z51fGmXBjsTQ@mail.gmail.com","subject":"Re: [PATCH v6 6/6] config: add '--show-scope' to print the scope of a config value","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-05T19:01:00Z","receivedAt":"2020-02-05T19:01:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n>> for clarity, I think this patch should be split up further.\n>>\n>> For example:\n>>\n>>   - moving an enum and adding a new entry should be avoided\n>\n> As far as adding a new entry, that could probably be done in a separate patch.\n> The submodule scoping is correct (mostly so config options that come from\n> submodule blobs have a sane value to set the new scope field of\n> git_config_source), but moving it is unavoidable as I'd either have to move\n> config_scope or git_config_source for this patch to work, and moving\n> git_config_source seemed like a ton more work\n>\n>>   - does the changes to '/config.c' fix something?\n>\n> Another thing, that in hindsight could probably be split out. The other changes\n> do fix the fact that previously recursive calls to do_git_config_sequence()\n> would blow awway the current_parsing_scope information for higher level callers.\n> This is not super common, but does occur when --show-scope is used with the\n> --blob option.\n>\n>>   - exposing config_scope_name should have been done before PATCH 4/6 already\n>\n> If that's better/more convenient, I don't have a problem breaking that\n> out and moving\n> it there.\n\nAlright.  Thanks for another round of review.\n"},{"id":"391428","messageId":"1c4faa7a367baf95d9940f4e9caa1904321601c7.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 01/10] config: fix typo in variable name","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:50Z","receivedAt":"2020-02-10T00:31:06Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nIn git config use of the end_null variable to determine if we should be\nnull terminating our output.  While it is correct to say a string is\n\"null terminated\" the character is actually the \"nul\" character, so this\nmalapropism is being fixed.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/config.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 98d65bc0ad..52a904cfb1 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -29,7 +29,7 @@ static int use_worktree_config;\n static struct git_config_source given_config_source;\n static int actions, type;\n static char *default_value;\n-static int end_null;\n+static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {\n \tOPT_CALLBACK_VALUE(0, \"path\", &type, N_(\"value is a path (file or directory name)\"), TYPE_PATH),\n \tOPT_CALLBACK_VALUE(0, \"expiry-date\", &type, N_(\"value is an expiry date\"), TYPE_EXPIRY_DATE),\n \tOPT_GROUP(N_(\"Other\")),\n-\tOPT_BOOL('z', \"null\", &end_null, N_(\"terminate values with NUL byte\")),\n+\tOPT_BOOL('z', \"null\", &end_nul, N_(\"terminate values with NUL byte\")),\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)\n \n static void show_config_origin(struct strbuf *buf)\n {\n-\tconst char term = end_null ? '\\0' : '\\t';\n+\tconst char term = end_nul ? '\\0' : '\\t';\n \n \tstrbuf_addstr(buf, current_config_origin_type());\n \tstrbuf_addch(buf, ':');\n-\tif (end_null)\n+\tif (end_nul)\n \t\tstrbuf_addstr(buf, current_config_name());\n \telse\n \t\tquote_c_style(current_config_name(), buf, NULL, 0);\n@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tconfig_options.git_dir = get_git_dir();\n \t}\n \n-\tif (end_null) {\n+\tif (end_nul) {\n \t\tterm = '\\0';\n \t\tdelim = '\\n';\n \t\tkey_delim = '\\n';\n-- \ngitgitgadget\n\n"},{"id":"391429","messageId":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v6.git.1580268865.gitgitgadget@gmail.com","subject":"[PATCH v7 00/10] config: allow user to know scope of config options","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:49Z","receivedAt":"2020-02-10T00:31:07Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"This was originally a pull request to the git-for-windows repository\n[https://github.com/git-for-windows/git/pull/2399]. It adds a new option\n--show-scope which would allow a user to see what scope a given\nconfiguration value has (sytem, local, global, etc.).\n\nchanges since v6: Split patch 6: config: add '--show-scope'... into several\nparts, including moving the exposure of config_scope_name into its own\ncommit earlier in the series.\n\nMatthew Rogers (10):\n  config: fix typo in variable name\n  t1300: fix over-indented HERE-DOCs\n  t1300: create custom config file without special characters\n  config: make scope_name non-static and rename it\n  config: split repo scope to local and worktree\n  config: clarify meaning of command line scoping\n  config: preserve scope in do_git_config_sequence\n  config: teach git_config_source to remember its scope\n  submodule-config: add subomdule config scope\n  config: add '--show-scope' to print the scope of a config value\n\n Documentation/git-config.txt |  15 ++-\n builtin/config.c             |  46 +++++--\n config.c                     |  35 ++++-\n config.h                     |  20 +--\n remote.c                     |   3 +-\n submodule-config.c           |   4 +-\n t/helper/test-config.c       |  17 +--\n t/t1300-config.sh            | 240 ++++++++++++++++++++++-------------\n t/t1308-config-set.sh        |   4 +-\n upload-pack.c                |   3 +-\n 10 files changed, 248 insertions(+), 139 deletions(-)\n\n\nbase-commit: de93cc14ab7e8db7645d8dbe4fd2603f76d5851f\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v7\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v7\nPull-Request: https://github.com/gitgitgadget/git/pull/478\n\nRange-diff vs v6:\n\n  1:  18f92f70cf =  1:  1c4faa7a36 config: fix typo in variable name\n  2:  dc7b3f3b96 =  2:  2c38c72f89 t1300: fix over-indented HERE-DOCs\n  3:  975e652368 =  3:  c832293ca7 t1300: create custom config file without special characters\n  -:  ---------- >  4:  14b0f27819 config: make scope_name non-static and rename it\n  4:  1e406ba430 !  5:  1af0237b8e config: split repo scope to local and worktree\n     @@ -45,6 +45,19 @@\n       \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n       \t\tchar *path = git_pathdup(\"config.worktree\");\n       \t\tif (!access_or_die(path, R_OK, 0))\n     +@@\n     + \t\treturn \"system\";\n     + \tcase CONFIG_SCOPE_GLOBAL:\n     + \t\treturn \"global\";\n     +-\tcase CONFIG_SCOPE_REPO:\n     +-\t\treturn \"repo\";\n     ++\tcase CONFIG_SCOPE_LOCAL:\n     ++\t\treturn \"local\";\n     ++\tcase CONFIG_SCOPE_WORKTREE:\n     ++\t\treturn \"worktree\";\n     + \tcase CONFIG_SCOPE_CMDLINE:\n     + \t\treturn \"command line\";\n     + \tdefault:\n      \n       diff --git a/config.h b/config.h\n       --- a/config.h\n     @@ -58,7 +71,7 @@\n      +\tCONFIG_SCOPE_WORKTREE,\n       \tCONFIG_SCOPE_CMDLINE,\n       };\n     - \n     + const char *config_scope_name(enum config_scope scope);\n      \n       diff --git a/remote.c b/remote.c\n       --- a/remote.c\n     @@ -74,23 +87,6 @@\n       \tif (!strcmp(subkey, \"mirror\"))\n       \t\tremote->mirror = git_config_bool(key, value);\n      \n     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n     - --- a/t/helper/test-config.c\n     - +++ b/t/helper/test-config.c\n     -@@\n     - \t\treturn \"system\";\n     - \tcase CONFIG_SCOPE_GLOBAL:\n     - \t\treturn \"global\";\n     --\tcase CONFIG_SCOPE_REPO:\n     --\t\treturn \"repo\";\n     -+\tcase CONFIG_SCOPE_LOCAL:\n     -+\t\treturn \"local\";\n     -+\tcase CONFIG_SCOPE_WORKTREE:\n     -+\t\treturn \"worktree\";\n     - \tcase CONFIG_SCOPE_CMDLINE:\n     - \t\treturn \"cmdline\";\n     - \tdefault:\n     -\n       diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n       --- a/t/t1308-config-set.sh\n       +++ b/t/t1308-config-set.sh\n  5:  936ce91c62 !  6:  64c20d0556 config: clarify meaning of command line scoping\n     @@ -26,6 +26,17 @@\n       \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n       \t\tdie(_(\"unable to parse command-line config\"));\n       \n     +@@\n     + \t\treturn \"local\";\n     + \tcase CONFIG_SCOPE_WORKTREE:\n     + \t\treturn \"worktree\";\n     +-\tcase CONFIG_SCOPE_CMDLINE:\n     +-\t\treturn \"command line\";\n     ++\tcase CONFIG_SCOPE_COMMAND:\n     ++\t\treturn \"command\";\n     + \tdefault:\n     + \t\treturn \"unknown\";\n     + \t}\n      \n       diff --git a/config.h b/config.h\n       --- a/config.h\n     @@ -37,23 +48,8 @@\n      -\tCONFIG_SCOPE_CMDLINE,\n      +\tCONFIG_SCOPE_COMMAND,\n       };\n     + const char *config_scope_name(enum config_scope scope);\n       \n     - enum config_scope current_config_scope(void);\n     -\n     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n     - --- a/t/helper/test-config.c\n     - +++ b/t/helper/test-config.c\n     -@@\n     - \t\treturn \"local\";\n     - \tcase CONFIG_SCOPE_WORKTREE:\n     - \t\treturn \"worktree\";\n     --\tcase CONFIG_SCOPE_CMDLINE:\n     --\t\treturn \"cmdline\";\n     -+\tcase CONFIG_SCOPE_COMMAND:\n     -+\t\treturn \"command\";\n     - \tdefault:\n     - \t\treturn \"unknown\";\n     - \t}\n      \n       diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n       --- a/t/t1308-config-set.sh\n     @@ -62,7 +58,7 @@\n       \tvalue=from-cmdline\n       \torigin=command line\n       \tname=\n     --\tscope=cmdline\n     +-\tscope=command line\n      +\tscope=command\n       \tEOF\n       \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n  -:  ---------- >  7:  f61985375c config: preserve scope in do_git_config_sequence\n  -:  ---------- >  8:  6c59c5cace config: teach git_config_source to remember its scope\n  -:  ---------- >  9:  dd376246ec submodule-config: add subomdule config scope\n  6:  fc141e8689 ! 10:  f76463ee90 config: add '--show-scope' to print the scope of a config value\n     @@ -12,7 +12,6 @@\n          parsing the '.gitmodules' file.\n      \n          Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n     -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n      \n       diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\n       --- a/Documentation/git-config.txt\n     @@ -108,212 +107,6 @@\n       \tif (show_origin)\n       \t\tshow_config_origin(buf);\n       \tif (show_keys)\n     -@@\n     - \t\t\t!strcmp(given_config_source.file, \"-\")) {\n     - \t\tgiven_config_source.file = NULL;\n     - \t\tgiven_config_source.use_stdin = 1;\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     - \t}\n     - \n     - \tif (use_global_config) {\n     -@@\n     - \t\t\t */\n     - \t\t\tdie(_(\"$HOME not set\"));\n     - \n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n     -+\n     - \t\tif (access_or_warn(user_config, R_OK, 0) &&\n     - \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n     - \t\t\tgiven_config_source.file = xdg_config;\n     -@@\n     - \t\t\tfree(xdg_config);\n     - \t\t}\n     - \t}\n     --\telse if (use_system_config)\n     -+\telse if (use_system_config) {\n     - \t\tgiven_config_source.file = git_etc_gitconfig();\n     --\telse if (use_local_config)\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n     -+\t} else if (use_local_config) {\n     - \t\tgiven_config_source.file = git_pathdup(\"config\");\n     --\telse if (use_worktree_config) {\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n     -+\t} else if (use_worktree_config) {\n     - \t\tstruct worktree **worktrees = get_worktrees(0);\n     - \t\tif (repository_format_worktree_config)\n     - \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n     -@@\n     - \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n     - \t\telse\n     - \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n     - \t\tfree_worktrees(worktrees);\n     - \t} else if (given_config_source.file) {\n     - \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n     - \t\t\tgiven_config_source.file =\n     - \t\t\t\tprefix_filename(prefix, given_config_source.file);\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     -+\t} else if (given_config_source.blob) {\n     -+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n     - \t}\n     - \n     -+\n     - \tif (respect_includes_opt == -1)\n     - \t\tconfig_options.respect_includes = !given_config_source.file;\n     - \telse\n     -\n     - diff --git a/config.c b/config.c\n     - --- a/config.c\n     - +++ b/config.c\n     -@@\n     - \tchar *xdg_config = xdg_config_home(\"config\");\n     - \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n     - \tchar *repo_config;\n     -+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n     - \n     - \tif (opts->commondir)\n     - \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n     -@@\n     - \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n     - \t\tdie(_(\"unable to parse command-line config\"));\n     - \n     --\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n     -+\tcurrent_parsing_scope = prev_parsing_scope;\n     - \tfree(xdg_config);\n     - \tfree(user_config);\n     - \tfree(repo_config);\n     -@@\n     - \t\tdata = &inc;\n     - \t}\n     - \n     -+\tif (config_source)\n     -+\t\tcurrent_parsing_scope = config_source->scope;\n     -+\n     - \t/*\n     - \t * If we have a specific filename, use it. Otherwise, follow the\n     - \t * regular lookup sequence.\n     -@@\n     - \t}\n     - }\n     - \n     -+const char *config_scope_name(enum config_scope scope)\n     -+{\n     -+\tswitch (scope) {\n     -+\tcase CONFIG_SCOPE_SYSTEM:\n     -+\t\treturn \"system\";\n     -+\tcase CONFIG_SCOPE_GLOBAL:\n     -+\t\treturn \"global\";\n     -+\tcase CONFIG_SCOPE_LOCAL:\n     -+\t\treturn \"local\";\n     -+\tcase CONFIG_SCOPE_WORKTREE:\n     -+\t\treturn \"worktree\";\n     -+\tcase CONFIG_SCOPE_COMMAND:\n     -+\t\treturn \"command\";\n     -+\tcase CONFIG_SCOPE_SUBMODULE:\n     -+\t\treturn \"submodule\";\n     -+\tdefault:\n     -+\t\treturn \"unknown\";\n     -+\t}\n     -+}\n     -+\n     - const char *current_config_name(void)\n     - {\n     - \tconst char *name;\n     -\n     - diff --git a/config.h b/config.h\n     - --- a/config.h\n     - +++ b/config.h\n     -@@\n     - \n     - #define CONFIG_REGEX_NONE ((void *)1)\n     - \n     -+enum config_scope {\n     -+\tCONFIG_SCOPE_UNKNOWN = 0,\n     -+\tCONFIG_SCOPE_SYSTEM,\n     -+\tCONFIG_SCOPE_GLOBAL,\n     -+\tCONFIG_SCOPE_LOCAL,\n     -+\tCONFIG_SCOPE_WORKTREE,\n     -+\tCONFIG_SCOPE_COMMAND,\n     -+\tCONFIG_SCOPE_SUBMODULE,\n     -+};\n     -+const char *config_scope_name(enum config_scope scope);\n     -+\n     - struct git_config_source {\n     - \tunsigned int use_stdin:1;\n     - \tconst char *file;\n     - \tconst char *blob;\n     -+\tenum config_scope scope;\n     - };\n     - \n     - enum config_origin_type {\n     -@@\n     - \n     - int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n     - \n     --enum config_scope {\n     --\tCONFIG_SCOPE_UNKNOWN = 0,\n     --\tCONFIG_SCOPE_SYSTEM,\n     --\tCONFIG_SCOPE_GLOBAL,\n     --\tCONFIG_SCOPE_LOCAL,\n     --\tCONFIG_SCOPE_WORKTREE,\n     --\tCONFIG_SCOPE_COMMAND,\n     --};\n     --\n     - enum config_scope current_config_scope(void);\n     - const char *current_config_origin_type(void);\n     - const char *current_config_name(void);\n     -\n     - diff --git a/submodule-config.c b/submodule-config.c\n     - --- a/submodule-config.c\n     - +++ b/submodule-config.c\n     -@@\n     - static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n     - {\n     - \tif (repo->worktree) {\n     --\t\tstruct git_config_source config_source = { 0 };\n     -+\t\tstruct git_config_source config_source = {\n     -+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n     -+\t\t};\n     - \t\tconst struct config_options opts = { 0 };\n     - \t\tstruct object_id oid;\n     - \t\tchar *file;\n     -\n     - diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n     - --- a/t/helper/test-config.c\n     - +++ b/t/helper/test-config.c\n     -@@\n     -  *\n     -  */\n     - \n     --static const char *scope_name(enum config_scope scope)\n     --{\n     --\tswitch (scope) {\n     --\tcase CONFIG_SCOPE_SYSTEM:\n     --\t\treturn \"system\";\n     --\tcase CONFIG_SCOPE_GLOBAL:\n     --\t\treturn \"global\";\n     --\tcase CONFIG_SCOPE_LOCAL:\n     --\t\treturn \"local\";\n     --\tcase CONFIG_SCOPE_WORKTREE:\n     --\t\treturn \"worktree\";\n     --\tcase CONFIG_SCOPE_COMMAND:\n     --\t\treturn \"command\";\n     --\tdefault:\n     --\t\treturn \"unknown\";\n     --\t}\n     --}\n     - static int iterate_cb(const char *var, const char *value, void *data)\n     - {\n     - \tstatic int nr;\n     -@@\n     - \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n     - \tprintf(\"origin=%s\\n\", current_config_origin_type());\n     - \tprintf(\"name=%s\\n\", current_config_name());\n     --\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n     -+\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n     - \n     - \treturn 0;\n     - }\n      \n       diff --git a/t/t1300-config.sh b/t/t1300-config.sh\n       --- a/t/t1300-config.sh\n\n-- \ngitgitgadget\n"},{"id":"391430","messageId":"c832293ca7ee3cb5013fe927cb2b97734e5039c4.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 03/10] t1300: create custom config file without special characters","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:52Z","receivedAt":"2020-02-10T00:31:07Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nTests that required a custom configuration file to be created previously\nused a file with non-alphanumeric characters including escaped double\nquotes.  This is not really necessary for the majority of tests\ninvolving custom config files, and decreases test coverage on systems\nthat dissallow such filenames (Windows, etc.).\n\nCreate two files, one appropriate for testing quoting and one\nappropriate for general use.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1300-config.sh | 15 ++++++++++-----\n 1 file changed, 10 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e8b4575758..e5fb9114f6 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1710,18 +1710,23 @@ test_expect_success '--show-origin getting a single key' '\n '\n \n test_expect_success 'set up custom config file' '\n-\tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tCUSTOM_CONFIG_FILE=\"custom.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n \t[user]\n \t\tcustom = true\n \tEOF\n '\n \n+test_expect_success !MINGW 'set up custom config file with special name characters' '\n+\tWEIRDLY_NAMED_FILE=\"file\\\" (dq) and spaces.conf\" &&\n+\tcp \"$CUSTOM_CONFIG_FILE\" \"$WEIRDLY_NAMED_FILE\"\n+'\n+\n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n \tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n-\tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n+\tgit config --file \"$WEIRDLY_NAMED_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n '\n \n@@ -1747,7 +1752,7 @@ test_expect_success '--show-origin stdin with file include' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob' '\n+test_expect_success '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n \tblob:$blob\tuser.custom=true\n@@ -1756,9 +1761,9 @@ test_expect_success !MINGW '--show-origin blob' '\n \ttest_cmp expect output\n '\n \n-test_expect_success !MINGW '--show-origin blob ref' '\n+test_expect_success '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:master:custom.conf\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"391431","messageId":"1af0237b8e76f0fd84ccac1e29d0cdc326303d7e.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 05/10] config: split repo scope to local and worktree","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:54Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPreviously when iterating through git config variables, worktree config\nand local config were both considered \"CONFIG_SCOPE_REPO\".  This was\nnever a problem before as no one had needed to differentiate between the\ntwo cases, but future functionality may care whether or not the config\noptions come from a worktree or from the repository's actual local\nconfig file.  For example, the planned feature to add a '--show-scope'\nto config to allow a user to see which scope listed config options come\nfrom would confuse users if it just printed 'repo' rather than 'local'\nor 'worktree' as the documentation would lead them to expect.  As well\nas the additional benefit of making the implementation look more like\nhow the documentation describes the interface.\n\nTo accomplish this we split out what was previously considered repo\nscope to be local and worktree.\n\nThe clients of 'current_config_scope()' who cared about\nCONFIG_SCOPE_REPO are also modified to similarly care about\nCONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n config.c              | 13 ++++++-------\n config.h              |  3 ++-\n remote.c              |  3 ++-\n t/t1308-config-set.sh |  2 +-\n upload-pack.c         |  3 ++-\n 5 files changed, 13 insertions(+), 11 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 83bb98d65e..7422bdebb1 100644\n--- a/config.c\n+++ b/config.c\n@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n \t\tret += git_config_from_file(fn, user_config, data);\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n \tif (!opts->ignore_repo && repo_config &&\n \t    !access_or_die(repo_config, R_OK, 0))\n \t\tret += git_config_from_file(fn, repo_config, data);\n \n-\t/*\n-\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n-\t * But let's not complicate things before it's actually needed.\n-\t */\n+\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n \t\tchar *path = git_pathdup(\"config.worktree\");\n \t\tif (!access_or_die(path, R_OK, 0))\n@@ -3304,8 +3301,10 @@ const char *config_scope_name(enum config_scope scope)\n \t\treturn \"system\";\n \tcase CONFIG_SCOPE_GLOBAL:\n \t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n-\t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_LOCAL:\n+\t\treturn \"local\";\n+\tcase CONFIG_SCOPE_WORKTREE:\n+\t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_CMDLINE:\n \t\treturn \"command line\";\n \tdefault:\ndiff --git a/config.h b/config.h\nindex dcb8c274d4..d3ed41ef8e 100644\n--- a/config.h\n+++ b/config.h\n@@ -299,7 +299,8 @@ enum config_scope {\n \tCONFIG_SCOPE_UNKNOWN = 0,\n \tCONFIG_SCOPE_SYSTEM,\n \tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_REPO,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_CMDLINE,\n };\n const char *config_scope_name(enum config_scope scope);\ndiff --git a/remote.c b/remote.c\nindex 5c4666b53a..593ce297ed 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t}\n \tremote = make_remote(name, namelen);\n \tremote->origin = REMOTE_CONFIG;\n-\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n+\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n+\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n \t\tremote->configured_in_repo = 1;\n \tif (!strcmp(subkey, \"mirror\"))\n \t\tremote->mirror = git_config_bool(key, value);\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 5f3e71a160..728a2b87ce 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-repo\n \torigin=file\n \tname=.git/config\n-\tscope=repo\n+\tscope=local\n \n \tkey=foo.bar\n \tvalue=from-cmdline\ndiff --git a/upload-pack.c b/upload-pack.c\nindex a00d7ece6b..c53249cac1 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n \t\tprecomposed_unicode = git_config_bool(var, value);\n \t}\n \n-\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n+\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n+\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n \t}\n-- \ngitgitgadget\n\n"},{"id":"391432","messageId":"2c38c72f898bff2b5d552ce25f4593622f4b6c8e.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 02/10] t1300: fix over-indented HERE-DOCs","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:51Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nPrepare for the following patches by removing extraneous indents from\nHERE-DOCs used in config tests.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n t/t1300-config.sh | 168 +++++++++++++++++++++++-----------------------\n 1 file changed, 84 insertions(+), 84 deletions(-)\n\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex 983a0a1583..e8b4575758 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1191,47 +1191,47 @@ test_expect_success 'old-fashioned settings are case insensitive' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQr = value2\n+\t[V.A]\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.a.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tQR = value2\n+\t[V.A]\n+\tQR = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.a.R\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"V.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n+\t[V.A]\n+\tr = value1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V.A]\n-\t\tr = value1\n-\t\tQr = value2\n+\t[V.A]\n+\tr = value1\n+\tQr = value2\n \tEOF\n \tgit config -f testConfig_actual \"v.A.r\" value2 &&\n \ttest_cmp testConfig_expect testConfig_actual\n@@ -1241,26 +1241,26 @@ test_expect_success 'setting different case sensitive subsections ' '\n \ttest_when_finished \"rm -f testConfig testConfig_expect testConfig_actual\" &&\n \n \tcat >testConfig_actual <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tR = v1\n-\t\t[K \"E\"]\n-\t\tY = v1\n-\t\t[a \"b\"]\n-\t\tc = v1\n-\t\t[d \"e\"]\n-\t\tf = v1\n+\t[V \"A\"]\n+\tR = v1\n+\t[K \"E\"]\n+\tY = v1\n+\t[a \"b\"]\n+\tc = v1\n+\t[d \"e\"]\n+\tf = v1\n \tEOF\n \tq_to_tab >testConfig_expect <<-EOF &&\n-\t\t[V \"A\"]\n-\t\tQr = v2\n-\t\t[K \"E\"]\n-\t\tQy = v2\n-\t\t[a \"b\"]\n-\t\tQc = v2\n-\t\t[d \"e\"]\n-\t\tf = v1\n-\t\t[d \"E\"]\n-\t\tQf = v2\n+\t[V \"A\"]\n+\tQr = v2\n+\t[K \"E\"]\n+\tQy = v2\n+\t[a \"b\"]\n+\tQc = v2\n+\t[d \"e\"]\n+\tf = v1\n+\t[d \"E\"]\n+\tQf = v2\n \tEOF\n \t# exact match\n \tgit config -f testConfig_actual a.b.c v2 &&\n@@ -1622,40 +1622,40 @@ test_expect_success 'set up --show-origin tests' '\n \tINCLUDE_DIR=\"$HOME/include\" &&\n \tmkdir -p \"$INCLUDE_DIR\" &&\n \tcat >\"$INCLUDE_DIR\"/absolute.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\tabsolute = include\n+\t[user]\n+\t\tabsolute = include\n \tEOF\n \tcat >\"$INCLUDE_DIR\"/relative.include <<-\\EOF &&\n-\t\t[user]\n-\t\t\trelative = include\n+\t[user]\n+\t\trelative = include\n \tEOF\n \tcat >\"$HOME\"/.gitconfig <<-EOF &&\n-\t\t[user]\n-\t\t\tglobal = true\n-\t\t\toverride = global\n-\t\t[include]\n-\t\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n+\t[user]\n+\t\tglobal = true\n+\t\toverride = global\n+\t[include]\n+\t\tpath = \"$INCLUDE_DIR/absolute.include\"\n \tEOF\n \tcat >.git/config <<-\\EOF\n-\t\t[user]\n-\t\t\tlocal = true\n-\t\t\toverride = local\n-\t\t[include]\n-\t\t\tpath = ../include/relative.include\n+\t[user]\n+\t\tlocal = true\n+\t\toverride = local\n+\t[include]\n+\t\tpath = ../include/relative.include\n \tEOF\n '\n \n test_expect_success '--show-origin with --list' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global=true\n-\t\tfile:$HOME/.gitconfig\tuser.override=global\n-\t\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n-\t\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n-\t\tfile:.git/../include/relative.include\tuser.relative=include\n-\t\tcommand line:\tuser.cmdline=true\n+\tfile:$HOME/.gitconfig\tuser.global=true\n+\tfile:$HOME/.gitconfig\tuser.override=global\n+\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand line:\tuser.cmdline=true\n \tEOF\n \tgit -c user.cmdline=true config --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1663,16 +1663,16 @@ test_expect_success '--show-origin with --list' '\n \n test_expect_success '--show-origin with --list --null' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfigQuser.global\n-\t\ttrueQfile:$HOME/.gitconfigQuser.override\n-\t\tglobalQfile:$HOME/.gitconfigQinclude.path\n-\t\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n-\t\tincludeQfile:.git/configQuser.local\n-\t\ttrueQfile:.git/configQuser.override\n-\t\tlocalQfile:.git/configQinclude.path\n-\t\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n-\t\tincludeQcommand line:Quser.cmdline\n-\t\ttrueQ\n+\tfile:$HOME/.gitconfigQuser.global\n+\ttrueQfile:$HOME/.gitconfigQuser.override\n+\tglobalQfile:$HOME/.gitconfigQinclude.path\n+\t$INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute\n+\tincludeQfile:.git/configQuser.local\n+\ttrueQfile:.git/configQuser.override\n+\tlocalQfile:.git/configQinclude.path\n+\t../include/relative.includeQfile:.git/../include/relative.includeQuser.relative\n+\tincludeQcommand line:Quser.cmdline\n+\ttrueQ\n \tEOF\n \tgit -c user.cmdline=true config --null --list --show-origin >output.raw &&\n \tnul_to_q <output.raw >output &&\n@@ -1684,9 +1684,9 @@ test_expect_success '--show-origin with --list --null' '\n \n test_expect_success '--show-origin with single file' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tuser.local=true\n-\t\tfile:.git/config\tuser.override=local\n-\t\tfile:.git/config\tinclude.path=../include/relative.include\n+\tfile:.git/config\tuser.local=true\n+\tfile:.git/config\tuser.override=local\n+\tfile:.git/config\tinclude.path=../include/relative.include\n \tEOF\n \tgit config --local --list --show-origin >output &&\n \ttest_cmp expect output\n@@ -1694,8 +1694,8 @@ test_expect_success '--show-origin with single file' '\n \n test_expect_success '--show-origin with --get-regexp' '\n \tcat >expect <<-EOF &&\n-\t\tfile:$HOME/.gitconfig\tuser.global true\n-\t\tfile:.git/config\tuser.local true\n+\tfile:$HOME/.gitconfig\tuser.global true\n+\tfile:.git/config\tuser.local true\n \tEOF\n \tgit config --show-origin --get-regexp \"user\\.[g|l].*\" >output &&\n \ttest_cmp expect output\n@@ -1703,7 +1703,7 @@ test_expect_success '--show-origin with --get-regexp' '\n \n test_expect_success '--show-origin getting a single key' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:.git/config\tlocal\n+\tfile:.git/config\tlocal\n \tEOF\n \tgit config --show-origin user.override >output &&\n \ttest_cmp expect output\n@@ -1712,14 +1712,14 @@ test_expect_success '--show-origin getting a single key' '\n test_expect_success 'set up custom config file' '\n \tCUSTOM_CONFIG_FILE=\"file\\\" (dq) and spaces.conf\" &&\n \tcat >\"$CUSTOM_CONFIG_FILE\" <<-\\EOF\n-\t\t[user]\n-\t\t\tcustom = true\n+\t[user]\n+\t\tcustom = true\n \tEOF\n '\n \n test_expect_success !MINGW '--show-origin escape special file name characters' '\n \tcat >expect <<-\\EOF &&\n-\t\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tfile:\"file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit config --file \"$CUSTOM_CONFIG_FILE\" --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1727,7 +1727,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '\n \n test_expect_success '--show-origin stdin' '\n \tcat >expect <<-\\EOF &&\n-\t\tstandard input:\tuser.custom=true\n+\tstandard input:\tuser.custom=true\n \tEOF\n \tgit config --file - --show-origin --list <\"$CUSTOM_CONFIG_FILE\" >output &&\n \ttest_cmp expect output\n@@ -1735,11 +1735,11 @@ test_expect_success '--show-origin stdin' '\n \n test_expect_success '--show-origin stdin with file include' '\n \tcat >\"$INCLUDE_DIR\"/stdin.include <<-EOF &&\n-\t\t[user]\n-\t\t\tstdin = include\n+\t[user]\n+\t\tstdin = include\n \tEOF\n \tcat >expect <<-EOF &&\n-\t\tfile:$INCLUDE_DIR/stdin.include\tinclude\n+\tfile:$INCLUDE_DIR/stdin.include\tinclude\n \tEOF\n \techo \"[include]path=\\\"$INCLUDE_DIR\\\"/stdin.include\" |\n \tgit config --show-origin --includes --file - user.stdin >output &&\n@@ -1750,7 +1750,7 @@ test_expect_success '--show-origin stdin with file include' '\n test_expect_success !MINGW '--show-origin blob' '\n \tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n \tcat >expect <<-EOF &&\n-\t\tblob:$blob\tuser.custom=true\n+\tblob:$blob\tuser.custom=true\n \tEOF\n \tgit config --blob=$blob --show-origin --list >output &&\n \ttest_cmp expect output\n@@ -1758,7 +1758,7 @@ test_expect_success !MINGW '--show-origin blob' '\n \n test_expect_success !MINGW '--show-origin blob ref' '\n \tcat >expect <<-\\EOF &&\n-\t\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n+\tblob:\"master:file\\\" (dq) and spaces.conf\"\tuser.custom=true\n \tEOF\n \tgit add \"$CUSTOM_CONFIG_FILE\" &&\n \tgit commit -m \"new config file\" &&\n-- \ngitgitgadget\n\n"},{"id":"391433","messageId":"f61985375c5096b863dc99ef613d864bfd010d96.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 07/10] config: preserve scope in do_git_config_sequence","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:56Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\ndo_git_config_sequence operated under the assumption that it was correct\nto set current_parsing_scope to CONFIG_SCOPE_UNKNOWN as part of the\ncleanup it does after it finishes execution.  This is incorrect, as it\nblows away the current_parsing_scope if do_git_config_sequence is called\nrecursively.  As such situations are rare (git config running with the\n'--blob' option is one example) this has yet to cause a problem, but the\nupcoming '--show-scope' option will experience issues in that case, lets\nteach do_git_config_sequence to preserve the current_parsing_scope from\nbefore it started execution.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/config.c b/config.c\nindex fe1e44a43a..0e2c693e78 100644\n--- a/config.c\n+++ b/config.c\n@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tchar *xdg_config = xdg_config_home(\"config\");\n \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n \tchar *repo_config;\n+\tenum config_scope prev_parsing_scope = current_parsing_scope;\n \n \tif (opts->commondir)\n \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n+\tcurrent_parsing_scope = prev_parsing_scope;\n \tfree(xdg_config);\n \tfree(user_config);\n \tfree(repo_config);\n-- \ngitgitgadget\n\n"},{"id":"391434","messageId":"64c20d0556e9e72663940da7f58a8e55a75fa9d0.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 06/10] config: clarify meaning of command line scoping","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:55Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nCONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\nvalues passed in via the -c option.  Options passed in using this\nmechanism share similar scoping characteristics with the --file and\n--blob options of the 'config' command, namely that they are only in use\nfor that single invocation of git, and that they supersede the normal\nsystem/global/local hierarchy.  This patch introduces\nCONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\nCONFIG_SCOPE_CMDLINE redundant.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n config.c              | 6 +++---\n config.h              | 2 +-\n t/t1308-config-set.sh | 2 +-\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 7422bdebb1..fe1e44a43a 100644\n--- a/config.c\n+++ b/config.c\n@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n \t\tfree(path);\n \t}\n \n-\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n+\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n \t\tdie(_(\"unable to parse command-line config\"));\n \n@@ -3305,8 +3305,8 @@ const char *config_scope_name(enum config_scope scope)\n \t\treturn \"local\";\n \tcase CONFIG_SCOPE_WORKTREE:\n \t\treturn \"worktree\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"command line\";\n+\tcase CONFIG_SCOPE_COMMAND:\n+\t\treturn \"command\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/config.h b/config.h\nindex d3ed41ef8e..b570f4ce43 100644\n--- a/config.h\n+++ b/config.h\n@@ -301,7 +301,7 @@ enum config_scope {\n \tCONFIG_SCOPE_GLOBAL,\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_CMDLINE,\n+\tCONFIG_SCOPE_COMMAND,\n };\n const char *config_scope_name(enum config_scope scope);\n \ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 728a2b87ce..fba0abe429 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=command line\n+\tscope=command\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n-- \ngitgitgadget\n\n"},{"id":"391435","messageId":"f76463ee90c1bc294ed503af19a47190f72778a8.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 10/10] config: add '--show-scope' to print the scope of a config value","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:59Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nWhen a user queries config values with --show-origin, often it's\ndifficult to determine what the actual \"scope\" (local, global, etc.) of\na given value is based on just the origin file.\n\nTeach 'git config' the '--show-scope' option to print the scope of all\ndisplayed config values.  Note that we should never see anything of\n\"submodule\" scope as that is only ever used by submodule-config.c when\nparsing the '.gitmodules' file.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n Documentation/git-config.txt | 15 ++++++---\n builtin/config.c             | 20 ++++++++++--\n t/t1300-config.sh            | 59 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 87 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 899e92a1c9..7573160f21 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -9,18 +9,18 @@ git-config - Get and set repository or global options\n SYNOPSIS\n --------\n [verse]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]\n 'git config' [<file-option>] [--type=<type>] --add name value\n 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]\n-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]\n+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]\n 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL\n 'git config' [<file-option>] --unset name [value_regex]\n 'git config' [<file-option>] --unset-all name [value_regex]\n 'git config' [<file-option>] --rename-section old_name new_name\n 'git config' [<file-option>] --remove-section name\n-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list\n+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list\n 'git config' [<file-option>] --get-color name [default]\n 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]\n 'git config' [<file-option>] -e | --edit\n@@ -222,6 +222,11 @@ Valid `<type>`'s include:\n \tthe actual origin (config file path, ref, or blob id if\n \tapplicable).\n \n+--show-scope::\n+\tSimilar to `--show-origin` in that it augments the output of\n+\tall queried config options with the scope of that value\n+\t(local, global, system, command).\n+\n --get-colorbool name [stdout-is-tty]::\n \n \tFind the color setting for `name` (e.g. `color.diff`) and output\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 0a9778b714..ee4aef6a35 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -33,6 +33,7 @@ static int end_nul;\n static int respect_includes_opt = -1;\n static struct config_options config_options;\n static int show_origin;\n+static int show_scope;\n \n #define ACTION_GET (1<<0)\n #define ACTION_GET_ALL (1<<1)\n@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {\n \tOPT_BOOL(0, \"name-only\", &omit_values, N_(\"show variable names only\")),\n \tOPT_BOOL(0, \"includes\", &respect_includes_opt, N_(\"respect include directives on lookup\")),\n \tOPT_BOOL(0, \"show-origin\", &show_origin, N_(\"show origin of config (file, standard input, blob, command line)\")),\n+\tOPT_BOOL(0, \"show-scope\", &show_scope, N_(\"show scope of config (worktree, local, global, system, command)\")),\n \tOPT_STRING(0, \"default\", &default_value, N_(\"value\"), N_(\"with --get, use default value when missing entry\")),\n \tOPT_END(),\n };\n@@ -189,11 +191,23 @@ static void show_config_origin(struct strbuf *buf)\n \tstrbuf_addch(buf, term);\n }\n \n+static void show_config_scope(struct strbuf *buf)\n+{\n+\tconst char term = end_nul ? '\\0' : '\\t';\n+\tconst char *scope = config_scope_name(current_config_scope());\n+\n+\tstrbuf_addstr(buf, N_(scope));\n+\tstrbuf_addch(buf, term);\n+}\n+\n static int show_all_config(const char *key_, const char *value_, void *cb)\n {\n-\tif (show_origin) {\n+\tif (show_origin || show_scope) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tshow_config_origin(&buf);\n+\t\tif (show_scope)\n+\t\t\tshow_config_scope(&buf);\n+\t\tif (show_origin)\n+\t\t\tshow_config_origin(&buf);\n \t\t/* Use fwrite as \"buf\" can contain \\0's if \"end_null\" is set. */\n \t\tfwrite(buf.buf, 1, buf.len, stdout);\n \t\tstrbuf_release(&buf);\n@@ -213,6 +227,8 @@ struct strbuf_list {\n \n static int format_config(struct strbuf *buf, const char *key_, const char *value_)\n {\n+\tif (show_scope)\n+\t\tshow_config_scope(buf);\n \tif (show_origin)\n \t\tshow_config_origin(buf);\n \tif (show_keys)\ndiff --git a/t/t1300-config.sh b/t/t1300-config.sh\nindex e5fb9114f6..5464c46c18 100755\n--- a/t/t1300-config.sh\n+++ b/t/t1300-config.sh\n@@ -1771,6 +1771,65 @@ test_expect_success '--show-origin blob ref' '\n \ttest_cmp expect output\n '\n \n+test_expect_success '--show-scope with --list' '\n+\tcat >expect <<-EOF &&\n+\tglobal\tuser.global=true\n+\tglobal\tuser.override=global\n+\tglobal\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tglobal\tuser.absolute=include\n+\tlocal\tuser.local=true\n+\tlocal\tuser.override=local\n+\tlocal\tinclude.path=../include/relative.include\n+\tlocal\tuser.relative=include\n+\tcommand\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success !MINGW '--show-scope with --blob' '\n+\tblob=$(git hash-object -w \"$CUSTOM_CONFIG_FILE\") &&\n+\tcat >expect <<-EOF &&\n+\tcommand\tuser.custom=true\n+\tEOF\n+\tgit config --blob=$blob --show-scope --list >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --local' '\n+\tcat >expect <<-\\EOF &&\n+\tlocal\tuser.local=true\n+\tlocal\tuser.override=local\n+\tlocal\tinclude.path=../include/relative.include\n+\tEOF\n+\tgit config --local --list --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope getting a single value' '\n+\tcat >expect <<-\\EOF &&\n+\tlocal\ttrue\n+\tEOF\n+\tgit config --show-scope --get user.local >output &&\n+\ttest_cmp expect output\n+'\n+\n+test_expect_success '--show-scope with --show-origin' '\n+\tcat >expect <<-EOF &&\n+\tglobal\tfile:$HOME/.gitconfig\tuser.global=true\n+\tglobal\tfile:$HOME/.gitconfig\tuser.override=global\n+\tglobal\tfile:$HOME/.gitconfig\tinclude.path=$INCLUDE_DIR/absolute.include\n+\tglobal\tfile:$INCLUDE_DIR/absolute.include\tuser.absolute=include\n+\tlocal\tfile:.git/config\tuser.local=true\n+\tlocal\tfile:.git/config\tuser.override=local\n+\tlocal\tfile:.git/config\tinclude.path=../include/relative.include\n+\tlocal\tfile:.git/../include/relative.include\tuser.relative=include\n+\tcommand\tcommand line:\tuser.cmdline=true\n+\tEOF\n+\tgit -c user.cmdline=true config --list --show-origin --show-scope >output &&\n+\ttest_cmp expect output\n+'\n+\n test_expect_success '--local requires a repo' '\n \t# we expect 128 to ensure that we do not simply\n \t# fail to find anything and return code \"1\"\n-- \ngitgitgadget\n"},{"id":"391438","messageId":"dd376246ec75e50b2e07f10ae7ec1e59c1e0572f.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 09/10] submodule-config: add subomdule config scope","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:58Z","receivedAt":"2020-02-10T00:31:14Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nBefore the changes to teach git_config_source to remember scope\ninformation submodule-config.c never needed to consider the question of\nconfig scope.  Even though zeroing out git_config_source is still\ncorrect and preserved the previous behavior of setting the scope to\nCONFIG_SCOPE_UNKNOWN, it's better to be explicit about such situations\nby explicitly setting the scope.  As none of the current config_scope\nenumerations make sense we create CONFIG_SCOPE_SUBMODULE to describe the\nsituation.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c           | 2 ++\n config.h           | 1 +\n submodule-config.c | 4 +++-\n 3 files changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/config.c b/config.c\nindex 9b6afca210..18a6bdd9ff 100644\n--- a/config.c\n+++ b/config.c\n@@ -3311,6 +3311,8 @@ const char *config_scope_name(enum config_scope scope)\n \t\treturn \"worktree\";\n \tcase CONFIG_SCOPE_COMMAND:\n \t\treturn \"command\";\n+\tcase CONFIG_SCOPE_SUBMODULE:\n+\t\treturn \"submodule\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/config.h b/config.h\nindex 165cacb7da..fe0addb0dc 100644\n--- a/config.h\n+++ b/config.h\n@@ -42,6 +42,7 @@ enum config_scope {\n \tCONFIG_SCOPE_LOCAL,\n \tCONFIG_SCOPE_WORKTREE,\n \tCONFIG_SCOPE_COMMAND,\n+\tCONFIG_SCOPE_SUBMODULE,\n };\n const char *config_scope_name(enum config_scope scope);\n \ndiff --git a/submodule-config.c b/submodule-config.c\nindex 85064810b2..b8e97d8ae8 100644\n--- a/submodule-config.c\n+++ b/submodule-config.c\n@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n {\n \tif (repo->worktree) {\n-\t\tstruct git_config_source config_source = { 0 };\n+\t\tstruct git_config_source config_source = {\n+\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n+\t\t};\n \t\tconst struct config_options opts = { 0 };\n \t\tstruct object_id oid;\n \t\tchar *file;\n-- \ngitgitgadget\n\n"},{"id":"391436","messageId":"6c59c5cace7e1f8fc16737c2c9dcf2016397caa1.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 08/10] config: teach git_config_source to remember its scope","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:57Z","receivedAt":"2020-02-10T00:31:15Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nThere are many situations where the scope of a config command is known\nbeforehand, such as passing of '--local', '--file', etc. to an\ninvocation of git config.  However, this information is lost when moving\nfrom builtin/config.c to /config.c.  This historically hasn't been a big\ndeal, but to prepare for the upcoming --show-scope option we teach\ngit_config_source to keep track of the source and the config machinery\nto use that information to set current_parsing_scope appropriately.\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n builtin/config.c | 16 +++++++++++++---\n config.c         |  3 +++\n config.h         | 20 ++++++++++----------\n 3 files changed, 26 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 52a904cfb1..0a9778b714 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -622,6 +622,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t!strcmp(given_config_source.file, \"-\")) {\n \t\tgiven_config_source.file = NULL;\n \t\tgiven_config_source.use_stdin = 1;\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n \tif (use_global_config) {\n@@ -637,6 +638,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t */\n \t\t\tdie(_(\"$HOME not set\"));\n \n+\t\tgiven_config_source.scope = CONFIG_SCOPE_GLOBAL;\n+\n \t\tif (access_or_warn(user_config, R_OK, 0) &&\n \t\t    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {\n \t\t\tgiven_config_source.file = xdg_config;\n@@ -646,11 +649,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\tfree(xdg_config);\n \t\t}\n \t}\n-\telse if (use_system_config)\n+\telse if (use_system_config) {\n \t\tgiven_config_source.file = git_etc_gitconfig();\n-\telse if (use_local_config)\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_SYSTEM;\n+\t} else if (use_local_config) {\n \t\tgiven_config_source.file = git_pathdup(\"config\");\n-\telse if (use_worktree_config) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n+\t} else if (use_worktree_config) {\n \t\tstruct worktree **worktrees = get_worktrees(0);\n \t\tif (repository_format_worktree_config)\n \t\t\tgiven_config_source.file = git_pathdup(\"config.worktree\");\n@@ -662,13 +667,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t      \"section in \\\"git help worktree\\\" for details\"));\n \t\telse\n \t\t\tgiven_config_source.file = git_pathdup(\"config\");\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_LOCAL;\n \t\tfree_worktrees(worktrees);\n \t} else if (given_config_source.file) {\n \t\tif (!is_absolute_path(given_config_source.file) && prefix)\n \t\t\tgiven_config_source.file =\n \t\t\t\tprefix_filename(prefix, given_config_source.file);\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n+\t} else if (given_config_source.blob) {\n+\t\tgiven_config_source.scope = CONFIG_SCOPE_COMMAND;\n \t}\n \n+\n \tif (respect_includes_opt == -1)\n \t\tconfig_options.respect_includes = !given_config_source.file;\n \telse\ndiff --git a/config.c b/config.c\nindex 0e2c693e78..9b6afca210 100644\n--- a/config.c\n+++ b/config.c\n@@ -1763,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,\n \t\tdata = &inc;\n \t}\n \n+\tif (config_source)\n+\t\tcurrent_parsing_scope = config_source->scope;\n+\n \t/*\n \t * If we have a specific filename, use it. Otherwise, follow the\n \t * regular lookup sequence.\ndiff --git a/config.h b/config.h\nindex b570f4ce43..165cacb7da 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,11 +35,21 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+enum config_scope {\n+\tCONFIG_SCOPE_UNKNOWN = 0,\n+\tCONFIG_SCOPE_SYSTEM,\n+\tCONFIG_SCOPE_GLOBAL,\n+\tCONFIG_SCOPE_LOCAL,\n+\tCONFIG_SCOPE_WORKTREE,\n+\tCONFIG_SCOPE_COMMAND,\n+};\n+const char *config_scope_name(enum config_scope scope);\n \n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n \tconst char *blob;\n+\tenum config_scope scope;\n };\n \n enum config_origin_type {\n@@ -295,16 +305,6 @@ int config_error_nonbool(const char *);\n \n int git_config_parse_parameter(const char *, config_fn_t fn, void *data);\n \n-enum config_scope {\n-\tCONFIG_SCOPE_UNKNOWN = 0,\n-\tCONFIG_SCOPE_SYSTEM,\n-\tCONFIG_SCOPE_GLOBAL,\n-\tCONFIG_SCOPE_LOCAL,\n-\tCONFIG_SCOPE_WORKTREE,\n-\tCONFIG_SCOPE_COMMAND,\n-};\n-const char *config_scope_name(enum config_scope scope);\n-\n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\n const char *current_config_name(void);\n-- \ngitgitgadget\n\n"},{"id":"391437","messageId":"14b0f278196ab9ab130402c2ef79adb0543655ef.1581294660.git.gitgitgadget@gmail.com","threadId":"52477","inReplyTo":"pull.478.v7.git.1581294660.gitgitgadget@gmail.com","subject":"[PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Matthew Rogers via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2020-02-10T00:30:53Z","receivedAt":"2020-02-10T00:31:17Z","isPatch":true,"sender":{"key":"name:Matthew Rogers","avatar":null},"body":"From: Matthew Rogers <mattr94@gmail.com>\n\nTo prepare for the upcoming --show-scope option, we require the ability\nto convert a config_scope enum to a string.  As this was originally\nimplemented as a static function 'scope_name()' in\nt/helper/test-config.c, we expose it via config.h and give it a less\nambiguous name 'config_scope_name()'\n\nSigned-off-by: Matthew Rogers <mattr94@gmail.com>\n---\n config.c               | 16 ++++++++++++++++\n config.h               |  2 ++\n t/helper/test-config.c | 17 +----------------\n t/t1308-config-set.sh  |  2 +-\n 4 files changed, 20 insertions(+), 17 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex d75f88ca0c..83bb98d65e 100644\n--- a/config.c\n+++ b/config.c\n@@ -3297,6 +3297,22 @@ const char *current_config_origin_type(void)\n \t}\n }\n \n+const char *config_scope_name(enum config_scope scope)\n+{\n+\tswitch (scope) {\n+\tcase CONFIG_SCOPE_SYSTEM:\n+\t\treturn \"system\";\n+\tcase CONFIG_SCOPE_GLOBAL:\n+\t\treturn \"global\";\n+\tcase CONFIG_SCOPE_REPO:\n+\t\treturn \"repo\";\n+\tcase CONFIG_SCOPE_CMDLINE:\n+\t\treturn \"command line\";\n+\tdefault:\n+\t\treturn \"unknown\";\n+\t}\n+}\n+\n const char *current_config_name(void)\n {\n \tconst char *name;\ndiff --git a/config.h b/config.h\nindex 91fd4c5e96..dcb8c274d4 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,6 +35,7 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n+\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\n@@ -301,6 +302,7 @@ enum config_scope {\n \tCONFIG_SCOPE_REPO,\n \tCONFIG_SCOPE_CMDLINE,\n };\n+const char *config_scope_name(enum config_scope scope);\n \n enum config_scope current_config_scope(void);\n const char *current_config_origin_type(void);\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex 214003d5b2..1e3bc7c8f4 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -37,21 +37,6 @@\n  *\n  */\n \n-static const char *scope_name(enum config_scope scope)\n-{\n-\tswitch (scope) {\n-\tcase CONFIG_SCOPE_SYSTEM:\n-\t\treturn \"system\";\n-\tcase CONFIG_SCOPE_GLOBAL:\n-\t\treturn \"global\";\n-\tcase CONFIG_SCOPE_REPO:\n-\t\treturn \"repo\";\n-\tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"cmdline\";\n-\tdefault:\n-\t\treturn \"unknown\";\n-\t}\n-}\n static int iterate_cb(const char *var, const char *value, void *data)\n {\n \tstatic int nr;\n@@ -63,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n \tprintf(\"origin=%s\\n\", current_config_origin_type());\n \tprintf(\"name=%s\\n\", current_config_name());\n-\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n+\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n \n \treturn 0;\n }\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 7b4e1a63eb..5f3e71a160 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=cmdline\n+\tscope=command line\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n-- \ngitgitgadget\n\n"},{"id":"391475","messageId":"xmqqd0am1fsc.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"14b0f278196ab9ab130402c2ef79adb0543655ef.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:02:59Z","receivedAt":"2020-02-10T18:03:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> To prepare for the upcoming --show-scope option, we require the ability\n> to convert a config_scope enum to a string.  As this was originally\n> implemented as a static function 'scope_name()' in\n> t/helper/test-config.c, we expose it via config.h and give it a less\n> ambiguous name 'config_scope_name()'\n\n\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  config.c               | 16 ++++++++++++++++\n>  config.h               |  2 ++\n>  t/helper/test-config.c | 17 +----------------\n>  t/t1308-config-set.sh  |  2 +-\n>  4 files changed, 20 insertions(+), 17 deletions(-)\n>\n> diff --git a/config.c b/config.c\n> index d75f88ca0c..83bb98d65e 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -3297,6 +3297,22 @@ const char *current_config_origin_type(void)\n>  \t}\n>  }\n>  \n> +const char *config_scope_name(enum config_scope scope)\n> +{\n> +\tswitch (scope) {\n> +\tcase CONFIG_SCOPE_SYSTEM:\n> +\t\treturn \"system\";\n> +\tcase CONFIG_SCOPE_GLOBAL:\n> +\t\treturn \"global\";\n> +\tcase CONFIG_SCOPE_REPO:\n> +\t\treturn \"repo\";\n> +\tcase CONFIG_SCOPE_CMDLINE:\n> +\t\treturn \"command line\";\n\nThe change from \"cmdline\" to \"command line\" does need to happen\nbefore the end of the series, but I do not think it should happen\nhere, especialy given that the proposed log message explains that\nthis step is to expose scope_name() under a better name (which is a\nvery good split point).\n\nHow are you reviewing the patches in your own series before sending\nthem out?  This round is better than the previous rounds where we\ndidn't have a matching change to the tests so \"make test\" may not\nhave passed in the middle of the series, though...\n\n> +\tdefault:\n> +\t\treturn \"unknown\";\n> +\t}\n> +}\n> +\n>  const char *current_config_name(void)\n>  {\n>  \tconst char *name;\n> diff --git a/config.h b/config.h\n> index 91fd4c5e96..dcb8c274d4 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -35,6 +35,7 @@ struct object_id;\n>  \n>  #define CONFIG_REGEX_NONE ((void *)1)\n>  \n> +\n>  struct git_config_source {\n>  \tunsigned int use_stdin:1;\n>  \tconst char *file;\n> @@ -301,6 +302,7 @@ enum config_scope {\n>  \tCONFIG_SCOPE_REPO,\n>  \tCONFIG_SCOPE_CMDLINE,\n>  };\n> +const char *config_scope_name(enum config_scope scope);\n>  \n>  enum config_scope current_config_scope(void);\n>  const char *current_config_origin_type(void);\n> diff --git a/t/helper/test-config.c b/t/helper/test-config.c\n> index 214003d5b2..1e3bc7c8f4 100644\n> --- a/t/helper/test-config.c\n> +++ b/t/helper/test-config.c\n> @@ -37,21 +37,6 @@\n>   *\n>   */\n>  \n> -static const char *scope_name(enum config_scope scope)\n> -{\n> -\tswitch (scope) {\n> -\tcase CONFIG_SCOPE_SYSTEM:\n> -\t\treturn \"system\";\n> -\tcase CONFIG_SCOPE_GLOBAL:\n> -\t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> -\t\treturn \"repo\";\n> -\tcase CONFIG_SCOPE_CMDLINE:\n> -\t\treturn \"cmdline\";\n> -\tdefault:\n> -\t\treturn \"unknown\";\n> -\t}\n> -}\n>  static int iterate_cb(const char *var, const char *value, void *data)\n>  {\n>  \tstatic int nr;\n> @@ -63,7 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data)\n>  \tprintf(\"value=%s\\n\", value ? value : \"(null)\");\n>  \tprintf(\"origin=%s\\n\", current_config_origin_type());\n>  \tprintf(\"name=%s\\n\", current_config_name());\n> -\tprintf(\"scope=%s\\n\", scope_name(current_config_scope()));\n> +\tprintf(\"scope=%s\\n\", config_scope_name(current_config_scope()));\n>  \n>  \treturn 0;\n>  }\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 7b4e1a63eb..5f3e71a160 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-cmdline\n>  \torigin=command line\n>  \tname=\n> -\tscope=cmdline\n> +\tscope=command line\n>  \tEOF\n>  \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n>  \ttest_cmp expect actual\n"},{"id":"391476","messageId":"xmqq8sla1flm.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"1af0237b8e76f0fd84ccac1e29d0cdc326303d7e.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 05/10] config: split repo scope to local and worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:07:01Z","receivedAt":"2020-02-10T18:07:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Previously when iterating through git config variables, worktree config\n> and local config were both considered \"CONFIG_SCOPE_REPO\".  This was\n> never a problem before as no one had needed to differentiate between the\n> two cases, but future functionality may care whether or not the config\n> options come from a worktree or from the repository's actual local\n> config file.  For example, the planned feature to add a '--show-scope'\n> to config to allow a user to see which scope listed config options come\n> from would confuse users if it just printed 'repo' rather than 'local'\n> or 'worktree' as the documentation would lead them to expect.  As well\n> as the additional benefit of making the implementation look more like\n> how the documentation describes the interface.\n>\n> To accomplish this we split out what was previously considered repo\n> scope to be local and worktree.\n>\n> The clients of 'current_config_scope()' who cared about\n> CONFIG_SCOPE_REPO are also modified to similarly care about\n> CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  config.c              | 13 ++++++-------\n>  config.h              |  3 ++-\n>  remote.c              |  3 ++-\n>  t/t1308-config-set.sh |  2 +-\n>  upload-pack.c         |  3 ++-\n>  5 files changed, 13 insertions(+), 11 deletions(-)\n\nMakes sense.  And this step does exactly what it claims to do and\nnothing else, which is very good ;-)  \n\n> diff --git a/config.c b/config.c\n> index 83bb98d65e..7422bdebb1 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tif (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))\n>  \t\tret += git_config_from_file(fn, user_config, data);\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_REPO;\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_LOCAL;\n>  \tif (!opts->ignore_repo && repo_config &&\n>  \t    !access_or_die(repo_config, R_OK, 0))\n>  \t\tret += git_config_from_file(fn, repo_config, data);\n>  \n> -\t/*\n> -\t * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.\n> -\t * But let's not complicate things before it's actually needed.\n> -\t */\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_WORKTREE;\n>  \tif (!opts->ignore_worktree && repository_format_worktree_config) {\n>  \t\tchar *path = git_pathdup(\"config.worktree\");\n>  \t\tif (!access_or_die(path, R_OK, 0))\n> @@ -3304,8 +3301,10 @@ const char *config_scope_name(enum config_scope scope)\n>  \t\treturn \"system\";\n>  \tcase CONFIG_SCOPE_GLOBAL:\n>  \t\treturn \"global\";\n> -\tcase CONFIG_SCOPE_REPO:\n> -\t\treturn \"repo\";\n> +\tcase CONFIG_SCOPE_LOCAL:\n> +\t\treturn \"local\";\n> +\tcase CONFIG_SCOPE_WORKTREE:\n> +\t\treturn \"worktree\";\n>  \tcase CONFIG_SCOPE_CMDLINE:\n>  \t\treturn \"command line\";\n>  \tdefault:\n> diff --git a/config.h b/config.h\n> index dcb8c274d4..d3ed41ef8e 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -299,7 +299,8 @@ enum config_scope {\n>  \tCONFIG_SCOPE_UNKNOWN = 0,\n>  \tCONFIG_SCOPE_SYSTEM,\n>  \tCONFIG_SCOPE_GLOBAL,\n> -\tCONFIG_SCOPE_REPO,\n> +\tCONFIG_SCOPE_LOCAL,\n> +\tCONFIG_SCOPE_WORKTREE,\n>  \tCONFIG_SCOPE_CMDLINE,\n>  };\n>  const char *config_scope_name(enum config_scope scope);\n> diff --git a/remote.c b/remote.c\n> index 5c4666b53a..593ce297ed 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n>  \t}\n>  \tremote = make_remote(name, namelen);\n>  \tremote->origin = REMOTE_CONFIG;\n> -\tif (current_config_scope() == CONFIG_SCOPE_REPO)\n> +\tif (current_config_scope() == CONFIG_SCOPE_LOCAL ||\n> +\tcurrent_config_scope() == CONFIG_SCOPE_WORKTREE)\n>  \t\tremote->configured_in_repo = 1;\n>  \tif (!strcmp(subkey, \"mirror\"))\n>  \t\tremote->mirror = git_config_bool(key, value);\n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 5f3e71a160..728a2b87ce 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -259,7 +259,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-repo\n>  \torigin=file\n>  \tname=.git/config\n> -\tscope=repo\n> +\tscope=local\n>  \n>  \tkey=foo.bar\n>  \tvalue=from-cmdline\n> diff --git a/upload-pack.c b/upload-pack.c\n> index a00d7ece6b..c53249cac1 100644\n> --- a/upload-pack.c\n> +++ b/upload-pack.c\n> @@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)\n>  \t\tprecomposed_unicode = git_config_bool(var, value);\n>  \t}\n>  \n> -\tif (current_config_scope() != CONFIG_SCOPE_REPO) {\n> +\tif (current_config_scope() != CONFIG_SCOPE_LOCAL &&\n> +\tcurrent_config_scope() != CONFIG_SCOPE_WORKTREE) {\n>  \t\tif (!strcmp(\"uploadpack.packobjectshook\", var))\n>  \t\t\treturn git_config_string(&pack_objects_hook, var, value);\n>  \t}\n"},{"id":"391477","messageId":"xmqq4kvy1fgj.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"64c20d0556e9e72663940da7f58a8e55a75fa9d0.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 06/10] config: clarify meaning of command line scoping","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:10:04Z","receivedAt":"2020-02-10T18:10:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config\n> values passed in via the -c option.  Options passed in using this\n> mechanism share similar scoping characteristics with the --file and\n> --blob options of the 'config' command, namely that they are only in use\n> for that single invocation of git, and that they supersede the normal\n> system/global/local hierarchy.  This patch introduces\n> CONFIG_SCOPE_COMMAND to reflect this new idea, which also makes\n> CONFIG_SCOPE_CMDLINE redundant.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  config.c              | 6 +++---\n>  config.h              | 2 +-\n>  t/t1308-config-set.sh | 2 +-\n>  3 files changed, 5 insertions(+), 5 deletions(-)\n\nThis makes sense, even though it is halfway undoing what 04/10\nunnecessarily did ;-)\n\nI think I can just wiggle minor fixes in to 04/10 and then adjust\nthis one to get the series into a better shape myself before queuing\nthem to expedite the process.  Let me finish reading the remainder\nof the topic.\n\nThanks.\n\n> diff --git a/config.c b/config.c\n> index 7422bdebb1..fe1e44a43a 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \t\tfree(path);\n>  \t}\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_CMDLINE;\n> +\tcurrent_parsing_scope = CONFIG_SCOPE_COMMAND;\n>  \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n>  \t\tdie(_(\"unable to parse command-line config\"));\n>  \n> @@ -3305,8 +3305,8 @@ const char *config_scope_name(enum config_scope scope)\n>  \t\treturn \"local\";\n>  \tcase CONFIG_SCOPE_WORKTREE:\n>  \t\treturn \"worktree\";\n> -\tcase CONFIG_SCOPE_CMDLINE:\n> -\t\treturn \"command line\";\n> +\tcase CONFIG_SCOPE_COMMAND:\n> +\t\treturn \"command\";\n>  \tdefault:\n>  \t\treturn \"unknown\";\n>  \t}\n> diff --git a/config.h b/config.h\n> index d3ed41ef8e..b570f4ce43 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -301,7 +301,7 @@ enum config_scope {\n>  \tCONFIG_SCOPE_GLOBAL,\n>  \tCONFIG_SCOPE_LOCAL,\n>  \tCONFIG_SCOPE_WORKTREE,\n> -\tCONFIG_SCOPE_CMDLINE,\n> +\tCONFIG_SCOPE_COMMAND,\n>  };\n>  const char *config_scope_name(enum config_scope scope);\n>  \n> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\n> index 728a2b87ce..fba0abe429 100755\n> --- a/t/t1308-config-set.sh\n> +++ b/t/t1308-config-set.sh\n> @@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n>  \tvalue=from-cmdline\n>  \torigin=command line\n>  \tname=\n> -\tscope=command line\n> +\tscope=command\n>  \tEOF\n>  \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n>  \ttest_cmp expect actual\n"},{"id":"391478","messageId":"xmqqzhdqz51f.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"f61985375c5096b863dc99ef613d864bfd010d96.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 07/10] config: preserve scope in do_git_config_sequence","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:11:08Z","receivedAt":"2020-02-10T18:11:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> do_git_config_sequence operated under the assumption that it was correct\n> to set current_parsing_scope to CONFIG_SCOPE_UNKNOWN as part of the\n> cleanup it does after it finishes execution.  This is incorrect, as it\n> blows away the current_parsing_scope if do_git_config_sequence is called\n> recursively.  As such situations are rare (git config running with the\n> '--blob' option is one example) this has yet to cause a problem, but the\n> upcoming '--show-scope' option will experience issues in that case, lets\n> teach do_git_config_sequence to preserve the current_parsing_scope from\n> before it started execution.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  config.c | 3 ++-\n>  1 file changed, 2 insertions(+), 1 deletion(-)\n\nThis step is new and it does make sense.\n\nThanks.\n\n\n\n> diff --git a/config.c b/config.c\n> index fe1e44a43a..0e2c693e78 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tchar *xdg_config = xdg_config_home(\"config\");\n>  \tchar *user_config = expand_user_path(\"~/.gitconfig\", 0);\n>  \tchar *repo_config;\n> +\tenum config_scope prev_parsing_scope = current_parsing_scope;\n>  \n>  \tif (opts->commondir)\n>  \t\trepo_config = mkpathdup(\"%s/config\", opts->commondir);\n> @@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,\n>  \tif (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)\n>  \t\tdie(_(\"unable to parse command-line config\"));\n>  \n> -\tcurrent_parsing_scope = CONFIG_SCOPE_UNKNOWN;\n> +\tcurrent_parsing_scope = prev_parsing_scope;\n>  \tfree(xdg_config);\n>  \tfree(user_config);\n>  \tfree(repo_config);\n"},{"id":"391479","messageId":"xmqqv9oez4wa.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"6c59c5cace7e1f8fc16737c2c9dcf2016397caa1.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 08/10] config: teach git_config_source to remember its scope","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:14:13Z","receivedAt":"2020-02-10T18:14:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> There are many situations where the scope of a config command is known\n> beforehand, such as passing of '--local', '--file', etc. to an\n> invocation of git config.  However, this information is lost when moving\n> from builtin/config.c to /config.c.  This historically hasn't been a big\n> deal, but to prepare for the upcoming --show-scope option we teach\n> git_config_source to keep track of the source and the config machinery\n> to use that information to set current_parsing_scope appropriately.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n>  builtin/config.c | 16 +++++++++++++---\n>  config.c         |  3 +++\n>  config.h         | 20 ++++++++++----------\n>  3 files changed, 26 insertions(+), 13 deletions(-)\n\nThis is split from the last step in the previous round, and the\nsplitting makes sense.\n\nThanks.\n"},{"id":"391480","messageId":"xmqqr1z2z4ui.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"dd376246ec75e50b2e07f10ae7ec1e59c1e0572f.1581294660.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v7 09/10] submodule-config: add subomdule config scope","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T18:15:17Z","receivedAt":"2020-02-10T18:15:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matthew Rogers via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Matthew Rogers <mattr94@gmail.com>\n>\n> Before the changes to teach git_config_source to remember scope\n> information submodule-config.c never needed to consider the question of\n> config scope.  Even though zeroing out git_config_source is still\n> correct and preserved the previous behavior of setting the scope to\n> CONFIG_SCOPE_UNKNOWN, it's better to be explicit about such situations\n> by explicitly setting the scope.  As none of the current config_scope\n> enumerations make sense we create CONFIG_SCOPE_SUBMODULE to describe the\n> situation.\n>\n> Signed-off-by: Matthew Rogers <mattr94@gmail.com>\n> ---\n\nOther than a typo on the title, I think this one is perfect ;-)\n\nWill queue.\n\n>  config.c           | 2 ++\n>  config.h           | 1 +\n>  submodule-config.c | 4 +++-\n>  3 files changed, 6 insertions(+), 1 deletion(-)\n>\n> diff --git a/config.c b/config.c\n> index 9b6afca210..18a6bdd9ff 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -3311,6 +3311,8 @@ const char *config_scope_name(enum config_scope scope)\n>  \t\treturn \"worktree\";\n>  \tcase CONFIG_SCOPE_COMMAND:\n>  \t\treturn \"command\";\n> +\tcase CONFIG_SCOPE_SUBMODULE:\n> +\t\treturn \"submodule\";\n>  \tdefault:\n>  \t\treturn \"unknown\";\n>  \t}\n> diff --git a/config.h b/config.h\n> index 165cacb7da..fe0addb0dc 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -42,6 +42,7 @@ enum config_scope {\n>  \tCONFIG_SCOPE_LOCAL,\n>  \tCONFIG_SCOPE_WORKTREE,\n>  \tCONFIG_SCOPE_COMMAND,\n> +\tCONFIG_SCOPE_SUBMODULE,\n>  };\n>  const char *config_scope_name(enum config_scope scope);\n>  \n> diff --git a/submodule-config.c b/submodule-config.c\n> index 85064810b2..b8e97d8ae8 100644\n> --- a/submodule-config.c\n> +++ b/submodule-config.c\n> @@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)\n>  static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)\n>  {\n>  \tif (repo->worktree) {\n> -\t\tstruct git_config_source config_source = { 0 };\n> +\t\tstruct git_config_source config_source = {\n> +\t\t\t0, .scope = CONFIG_SCOPE_SUBMODULE\n> +\t\t};\n>  \t\tconst struct config_options opts = { 0 };\n>  \t\tstruct object_id oid;\n>  \t\tchar *file;\n"},{"id":"391493","messageId":"xmqqzhdqxhg9.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"xmqqd0am1fsc.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-10T21:25:58Z","receivedAt":"2020-02-10T21:26:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> The change from \"cmdline\" to \"command line\" does need to happen\n> before the end of the series, but I do not think it should happen\n> here, especialy given that the proposed log message explains that\n> this step is to expose scope_name() under a better name (which is a\n> very good split point).\n\nI'll tweak this step with the attached patch, and then adjust\n06/10 as needed, while queuing.\n\n config.c              | 2 +-\n config.h              | 1 -\n t/t1308-config-set.sh | 2 +-\n 3 files changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 83bb98d65e..a922b136e5 100644\n--- a/config.c\n+++ b/config.c\n@@ -3307,7 +3307,7 @@ const char *config_scope_name(enum config_scope scope)\n \tcase CONFIG_SCOPE_REPO:\n \t\treturn \"repo\";\n \tcase CONFIG_SCOPE_CMDLINE:\n-\t\treturn \"command line\";\n+\t\treturn \"cmdline\";\n \tdefault:\n \t\treturn \"unknown\";\n \t}\ndiff --git a/config.h b/config.h\nindex dcb8c274d4..c063f33ff6 100644\n--- a/config.h\n+++ b/config.h\n@@ -35,7 +35,6 @@ struct object_id;\n \n #define CONFIG_REGEX_NONE ((void *)1)\n \n-\n struct git_config_source {\n \tunsigned int use_stdin:1;\n \tconst char *file;\ndiff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh\nindex 5f3e71a160..7b4e1a63eb 100755\n--- a/t/t1308-config-set.sh\n+++ b/t/t1308-config-set.sh\n@@ -265,7 +265,7 @@ test_expect_success 'iteration shows correct origins' '\n \tvalue=from-cmdline\n \torigin=command line\n \tname=\n-\tscope=command line\n+\tscope=cmdline\n \tEOF\n \tGIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&\n \ttest_cmp expect actual\n"},{"id":"391516","messageId":"CAOjrSZvm-3qVw4880MeDVk59ToCwp9vMC1zFp-SYaDsFd3Y=8g@mail.gmail.com","threadId":"52477","inReplyTo":"xmqqd0am1fsc.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-02-11T00:30:22Z","receivedAt":"2020-02-11T00:30:36Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":">\n> How are you reviewing the patches in your own series before sending\n> them out?  This round is better than the previous rounds where we\n> didn't have a matching change to the tests so \"make test\" may not\n> have passed in the middle of the series, though...\n>\n\nI went through each patch individually using rebase -i and built/tested it.\nAlthough just to save time I only did t1300 and t1308 since I believe those were\nthe only ones that should be affected.  I can write a script that\nwould run the whole\ntest suite overnight for me and make sure the series shakes out okay,\nif you'd like.\n"},{"id":"391517","messageId":"20200211015811.GE190927@google.com","threadId":"52477","inReplyTo":"CAOjrSZvm-3qVw4880MeDVk59ToCwp9vMC1zFp-SYaDsFd3Y=8g@mail.gmail.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Emily Shaffer","fromEmail":"emilyshaffer@google.com","sentAt":"2020-02-11T01:58:11Z","receivedAt":"2020-02-11T01:58:18Z","isPatch":true,"sender":{"key":"nasamuffin@google.com","avatar":"https://avatars.githubusercontent.com/u/1606826?v=4"},"body":"On Mon, Feb 10, 2020 at 07:30:22PM -0500, Matt Rogers wrote:\n> >\n> > How are you reviewing the patches in your own series before sending\n> > them out?  This round is better than the previous rounds where we\n> > didn't have a matching change to the tests so \"make test\" may not\n> > have passed in the middle of the series, though...\n> >\n> \n> I went through each patch individually using rebase -i and built/tested it.\n> Although just to save time I only did t1300 and t1308 since I believe those were\n> the only ones that should be affected.  I can write a script that\n> would run the whole\n> test suite overnight for me and make sure the series shakes out okay,\n> if you'd like.\n\nNot sure whether you intend to do this or not, but to maybe save you\nsome scripting, I do this like so:\n\n  git rebase -x \\\n    \"make -j16 && (cd t && prove -j16 -v --shuffle t[0-9]*.sh)\" master\n\nIf the tests fail, the rebase is paused, which can be understandably\ndisappointing if you walk away from it overnight only to have it fail\nafter 10 minutes, though. :)\n\n - Emily\n"},{"id":"391523","messageId":"xmqq5zgdy7pu.fsf@gitster-ct.c.googlers.com","threadId":"52477","inReplyTo":"CAOjrSZvm-3qVw4880MeDVk59ToCwp9vMC1zFp-SYaDsFd3Y=8g@mail.gmail.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-02-11T06:10:53Z","receivedAt":"2020-02-11T06:10:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matt Rogers <mattr94@gmail.com> writes:\n\n>> How are you reviewing the patches in your own series before sending\n>> them out?  This round is better than the previous rounds where we\n>> didn't have a matching change to the tests so \"make test\" may not\n>> have passed in the middle of the series, though...\n>>\n>\n> I went through each patch individually using rebase -i and built/tested it.\n> Although just to save time I only did t1300 and t1308 since I believe those were\n> the only ones that should be affected.  I can write a script that\n> would run the whole\n> test suite overnight for me and make sure the series shakes out okay,\n> if you'd like.\n\nWhat I like does not matter.  \n\nWhat I pointed out for 04/10 wouldn't have been caught by your\ntesting anyway, as both the code and the test had matching\nunnecessry changes.  I was wondering if you are relying too heavily\non just tests and without actually proofreading the changes to see\nif they still make sense in the context of the updated series, and\nif my suspicion was correct, if there are something reviewers can do\nto help the authors.\n\n\n"},{"id":"391525","messageId":"CAOjrSZs7aN08joo9mjvw6EvLHRRKofETVzAWvPuQAo1rBwZMvw@mail.gmail.com","threadId":"52477","inReplyTo":"xmqq5zgdy7pu.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v7 04/10] config: make scope_name non-static and rename it","fromName":"Matt Rogers","fromEmail":"mattr94@gmail.com","sentAt":"2020-02-11T12:37:32Z","receivedAt":"2020-02-11T12:37:46Z","isPatch":true,"sender":{"key":"mattr94@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5719846?v=4"},"body":"On Tue, Feb 11, 2020 at 1:10 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Matt Rogers <mattr94@gmail.com> writes:\n>\n> >> How are you reviewing the patches in your own series before sending\n> >> them out?  This round is better than the previous rounds where we\n> >> didn't have a matching change to the tests so \"make test\" may not\n> >> have passed in the middle of the series, though...\n> >>\n> >\n> > I went through each patch individually using rebase -i and built/tested it.\n> > Although just to save time I only did t1300 and t1308 since I believe those were\n> > the only ones that should be affected.  I can write a script that\n> > would run the whole\n> > test suite overnight for me and make sure the series shakes out okay,\n> > if you'd like.\n>\n> What I like does not matter.\n>\n> What I pointed out for 04/10 wouldn't have been caught by your\n> testing anyway, as both the code and the test had matching\n> unnecessry changes.  I was wondering if you are relying too heavily\n> on just tests and without actually proofreading the changes to see\n> if they still make sense in the context of the updated series, and\n> if my suspicion was correct, if there are something reviewers can do\n> to help the authors.\n>\n>\n\nI do try to proofread patches, I'm just not the most careful of reviewers at\ntimes, partially as a personal problem and partially as this is a new workflow\nfor me.  As for the particular issue, I just thought it was a good idea at the\ntime and I didn't think it all the way through\n\n\n-- \nMatthew Rogers\n"}]}