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