From: Lars Schneider <larsxschneider@xxxxxxxxx> If config values are queried using 'git config' (e.g. via '--list' flag or the '--get*' flags) then it is sometimes hard to find the configuration file where the values were defined. Teach 'git config' the '--sources' option to print the source configuration file for every printed value. Based-on-patch-by: Jeff King <peff@xxxxxxxx> Signed-off-by: Lars Schneider <larsxschneider@xxxxxxxxx> --- builtin/config.c | 42 ++++++++++++++++++++++++++++++++ cache.h | 1 + config.c | 7 ++++++ t/t1300-repo-config.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) diff --git a/builtin/config.c b/builtin/config.c index adc7727..f5dc79c 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -3,6 +3,7 @@ #include "color.h" #include "parse-options.h" #include "urlmatch.h" +#include "quote.h" static const char *const builtin_config_usage[] = { N_("git config [<options>]"), @@ -27,6 +28,7 @@ static int actions, types; static const char *get_color_slot, *get_colorbool_slot; static int end_null; static int respect_includes = -1; +static int show_sources; #define ACTION_GET (1<<0) #define ACTION_GET_ALL (1<<1) @@ -81,6 +83,7 @@ static struct option builtin_config_options[] = { OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")), OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")), + OPT_BOOL(0, "sources", &show_sources, N_("show source filenames of config")), OPT_END(), }; @@ -91,8 +94,34 @@ static void check_argc(int argc, int min, int max) { usage_with_options(builtin_config_usage, builtin_config_options); } +/* output to either fp or buf; only one should be non-NULL */ +static void show_config_source(struct strbuf *buf, FILE *fp) +{ + const char *fn = current_config_filename(); + if (!fn) + return; + + char term = '\t'; + if (!end_null) + quote_c_style(fn, buf, fp, 0); + else { + term = '\0'; + if (fp) + fprintf(fp, "%s", fn); + else + strbuf_addstr(buf, fn); + } + + if (fp) + fputc(term, fp); + else + strbuf_addch(buf, term); +} + static int show_all_config(const char *key_, const char *value_, void *cb) { + if (show_sources) + show_config_source(NULL, stdout); if (!omit_values && value_) printf("%s%c%s%c", key_, delim, value_, term); else @@ -108,6 +137,8 @@ struct strbuf_list { static int format_config(struct strbuf *buf, const char *key_, const char *value_) { + if (show_sources) + show_config_source(buf, NULL); if (show_keys) strbuf_addstr(buf, key_); if (!omit_values) { @@ -538,6 +569,17 @@ int cmd_config(int argc, const char **argv, const char *prefix) error("--name-only is only applicable to --list or --get-regexp"); usage_with_options(builtin_config_usage, builtin_config_options); } + + const int is_query_action = actions & ( + ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST| + ACTION_GET_COLOR|ACTION_GET_COLORBOOL|ACTION_GET_URLMATCH + ); + + if (show_sources && !is_query_action) { + error("--sources is only applicable to --list or --get-* actions"); + usage_with_options(builtin_config_usage, builtin_config_options); + } + if (actions == ACTION_LIST) { check_argc(argc, 0, 0); if (git_config_with_options(show_all_config, NULL, diff --git a/cache.h b/cache.h index c63fcc1..c5111ea 100644 --- a/cache.h +++ b/cache.h @@ -1525,6 +1525,7 @@ extern const char *get_log_output_encoding(void); extern const char *get_commit_output_encoding(void); extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data); +extern const char *current_config_filename(void); struct config_include_data { int depth; diff --git a/config.c b/config.c index 86a5eb2..b437002 100644 --- a/config.c +++ b/config.c @@ -2385,3 +2385,10 @@ int parse_config_key(const char *var, return 0; } + +const char *current_config_filename(void) +{ + if (cf && cf->name) + return cf->name; + return NULL; +} diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 52678e7..2444d8a 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -1201,4 +1201,69 @@ test_expect_success POSIXPERM,PERL 'preserves existing permissions' ' "die q(badrename) if ((stat(q(.git/config)))[2] & 07777) != 0600" ' +test_expect_success '--sources' ' + >.git/config && + >"$HOME"/.gitconfig && + INCLUDE_DIR="$HOME/include" && + mkdir -p "$INCLUDE_DIR" && + cat >"$INCLUDE_DIR"/include.conf <<-EOF && + [user] + include = true + EOF + cat >"$HOME"/file.conf <<-EOF && + [user] + custom = true + EOF + test_config_global user.global "true" && + test_config_global user.override "global" && + test_config_global include.path "$INCLUDE_DIR"/include.conf && + test_config user.local "true" && + test_config user.override "local" && + + cat >expect <<-EOF && + $HOME/.gitconfig user.global=true + $HOME/.gitconfig user.override=global + $HOME/.gitconfig include.path=$INCLUDE_DIR/include.conf + $INCLUDE_DIR/include.conf user.include=true + .git/config user.local=true + .git/config user.override=local + user.cmdline=true + EOF + git -c user.cmdline=true config --list --sources >output && + test_cmp expect output && + + cat >expect <<-EOF && + $HOME/.gitconfigQuser.global + trueQ$HOME/.gitconfigQuser.override + globalQ$HOME/.gitconfigQinclude.path + $INCLUDE_DIR/include.confQ$INCLUDE_DIR/include.confQuser.include + trueQ.git/configQuser.local + trueQ.git/configQuser.override + localQuser.cmdline + trueQ + EOF + git -c user.cmdline=true config --null --list --sources | nul_to_q >output && + echo >>output && + test_cmp expect output && + + cat >expect <<-EOF && + .git/config local + EOF + git config --sources user.override >output && + test_cmp expect output && + + cat >expect <<-EOF && + $HOME/file.conf user.custom=true + EOF + git config --file "$HOME"/file.conf --sources --list >output && + test_cmp expect output && + + cat >expect <<-EOF && + a9d9f9e555b5c6f07cbe09d3f06fe3df11e09c08 user.custom=true + EOF + blob=$(git hash-object -w "$HOME"/file.conf) && + git config --blob=$blob --sources --list >output && + test_cmp expect output +' + test_done -- 2.5.1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html