diff options
-rw-r--r-- | builtin/config.c | 21 | ||||
-rw-r--r-- | cache.h | 8 | ||||
-rw-r--r-- | config.c | 62 | ||||
-rwxr-xr-x | t/t1305-config-include.sh | 11 | ||||
-rwxr-xr-x | t/t1309-early-config.sh | 18 |
5 files changed, 90 insertions, 30 deletions
diff --git a/builtin/config.c b/builtin/config.c index 3f7c8763d2..1b7ed5af08 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -26,7 +26,8 @@ static int use_global_config, use_system_config, use_local_config; static struct git_config_source given_config_source; static int actions, types; static int end_null; -static int respect_includes = -1; +static int respect_includes_opt = -1; +static struct config_options config_options; static int show_origin; #define ACTION_GET (1<<0) @@ -81,7 +82,7 @@ static struct option builtin_config_options[] = { OPT_GROUP(N_("Other")), 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, "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_END(), }; @@ -242,7 +243,7 @@ static int get_value(const char *key_, const char *regex_) } git_config_with_options(collect_config, &values, - &given_config_source, respect_includes); + &given_config_source, &config_options); ret = !values.nr; @@ -320,7 +321,7 @@ static void get_color(const char *var, const char *def_color) get_color_found = 0; parsed_color[0] = '\0'; git_config_with_options(git_get_color_config, NULL, - &given_config_source, respect_includes); + &given_config_source, &config_options); if (!get_color_found && def_color) { if (color_parse(def_color, parsed_color) < 0) @@ -352,7 +353,7 @@ static int get_colorbool(const char *var, int print) get_diff_color_found = -1; get_color_ui_found = -1; git_config_with_options(git_get_colorbool_config, NULL, - &given_config_source, respect_includes); + &given_config_source, &config_options); if (get_colorbool_found < 0) { if (!strcmp(get_colorbool_slot, "color.diff")) @@ -441,7 +442,7 @@ static int get_urlmatch(const char *var, const char *url) } git_config_with_options(urlmatch_config_entry, &config, - &given_config_source, respect_includes); + &given_config_source, &config_options); ret = !values.nr; @@ -530,8 +531,10 @@ int cmd_config(int argc, const char **argv, const char *prefix) prefix_filename(prefix, given_config_source.file); } - if (respect_includes == -1) - respect_includes = !given_config_source.file; + if (respect_includes_opt == -1) + config_options.respect_includes = !given_config_source.file; + else + config_options.respect_includes = respect_includes_opt; if (end_null) { term = '\0'; @@ -578,7 +581,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_argc(argc, 0, 0); if (git_config_with_options(show_all_config, NULL, &given_config_source, - respect_includes) < 0) { + &config_options) < 0) { if (given_config_source.file) die_errno("unable to read config file '%s'", given_config_source.file); @@ -1891,6 +1891,11 @@ enum config_origin_type { CONFIG_ORIGIN_CMDLINE }; +struct config_options { + unsigned int respect_includes : 1; + const char *git_dir; +}; + typedef int (*config_fn_t)(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *); extern int git_config_from_file(config_fn_t fn, const char *, void *); @@ -1904,7 +1909,7 @@ extern void read_early_config(config_fn_t cb, void *data); extern void git_config(config_fn_t fn, void *); extern int git_config_with_options(config_fn_t fn, void *, struct git_config_source *config_source, - int respect_includes); + const struct config_options *opts); extern int git_parse_ulong(const char *, unsigned long *); extern int git_parse_maybe_bool(const char *); extern int git_config_int(const char *, const char *); @@ -1957,6 +1962,7 @@ struct config_include_data { int depth; config_fn_t fn; void *data; + const struct config_options *opts; }; #define CONFIG_INCLUDE_INIT { 0 } extern int git_config_include(const char *name, const char *value, void *data); @@ -207,13 +207,22 @@ static int prepare_include_condition_pattern(struct strbuf *pat) return prefix; } -static int include_by_gitdir(const char *cond, size_t cond_len, int icase) +static int include_by_gitdir(const struct config_options *opts, + const char *cond, size_t cond_len, int icase) { struct strbuf text = STRBUF_INIT; struct strbuf pattern = STRBUF_INIT; int ret = 0, prefix; + const char *git_dir; - strbuf_realpath(&text, get_git_dir(), 1); + if (opts->git_dir) + git_dir = opts->git_dir; + else if (have_git_dir()) + git_dir = get_git_dir(); + else + goto done; + + strbuf_realpath(&text, git_dir, 1); strbuf_add(&pattern, cond, cond_len); prefix = prepare_include_condition_pattern(&pattern); @@ -242,13 +251,14 @@ done: return ret; } -static int include_condition_is_true(const char *cond, size_t cond_len) +static int include_condition_is_true(const struct config_options *opts, + const char *cond, size_t cond_len) { if (skip_prefix_mem(cond, cond_len, "gitdir:", &cond, &cond_len)) - return include_by_gitdir(cond, cond_len, 0); + return include_by_gitdir(opts, cond, cond_len, 0); else if (skip_prefix_mem(cond, cond_len, "gitdir/i:", &cond, &cond_len)) - return include_by_gitdir(cond, cond_len, 1); + return include_by_gitdir(opts, cond, cond_len, 1); /* unknown conditionals are always false */ return 0; @@ -273,7 +283,7 @@ int git_config_include(const char *var, const char *value, void *data) ret = handle_path_include(value, inc); if (!parse_config_key(var, "includeif", &cond, &cond_len, &key) && - (cond && include_condition_is_true(cond, cond_len)) && + (cond && include_condition_is_true(inc->opts, cond, cond_len)) && !strcmp(key, "path")) ret = handle_path_include(value, inc); @@ -1511,12 +1521,20 @@ int git_config_system(void) return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0); } -static int do_git_config_sequence(config_fn_t fn, void *data) +static int do_git_config_sequence(const struct config_options *opts, + config_fn_t fn, void *data) { int ret = 0; char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig", 0); - char *repo_config = have_git_dir() ? git_pathdup("config") : NULL; + char *repo_config; + + if (opts->git_dir) + repo_config = mkpathdup("%s/config", opts->git_dir); + else if (have_git_dir()) + repo_config = git_pathdup("config"); + else + repo_config = NULL; current_parsing_scope = CONFIG_SCOPE_SYSTEM; if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) @@ -1547,13 +1565,14 @@ static int do_git_config_sequence(config_fn_t fn, void *data) int git_config_with_options(config_fn_t fn, void *data, struct git_config_source *config_source, - int respect_includes) + const struct config_options *opts) { struct config_include_data inc = CONFIG_INCLUDE_INIT; - if (respect_includes) { + if (opts->respect_includes) { inc.fn = fn; inc.data = data; + inc.opts = opts; fn = git_config_include; data = &inc; } @@ -1569,12 +1588,15 @@ int git_config_with_options(config_fn_t fn, void *data, else if (config_source && config_source->blob) return git_config_from_blob_ref(fn, config_source->blob, data); - return do_git_config_sequence(fn, data); + return do_git_config_sequence(opts, fn, data); } static void git_config_raw(config_fn_t fn, void *data) { - if (git_config_with_options(fn, data, NULL, 1) < 0) + struct config_options opts = {0}; + + opts.respect_includes = 1; + if (git_config_with_options(fn, data, NULL, &opts) < 0) /* * git_config_with_options() normally returns only * zero, as most errors are fatal, and @@ -1614,10 +1636,13 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data) void read_early_config(config_fn_t cb, void *data) { + struct config_options opts = {0}; struct strbuf buf = STRBUF_INIT; - git_config_with_options(cb, data, NULL, 1); + opts.respect_includes = 1; + if (have_git_dir()) + opts.git_dir = get_git_dir(); /* * When setup_git_directory() was not yet asked to discover the * GIT_DIR, we ask discover_git_directory() to figure out whether there @@ -1626,14 +1651,11 @@ void read_early_config(config_fn_t cb, void *data) * notably, the current working directory is still the same after the * call). */ - if (!have_git_dir() && discover_git_directory(&buf)) { - struct git_config_source repo_config; + else if (discover_git_directory(&buf)) + opts.git_dir = buf.buf; + + git_config_with_options(cb, data, NULL, &opts); - memset(&repo_config, 0, sizeof(repo_config)); - strbuf_addstr(&buf, "/config"); - repo_config.file = buf.buf; - git_config_with_options(cb, data, &repo_config, 1); - } strbuf_release(&buf); } diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index 8fbc7a029f..933915ec06 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -218,6 +218,17 @@ test_expect_success 'conditional include, both unanchored, icase' ' ) ' +test_expect_success 'conditional include, early config reading' ' + ( + cd foo && + echo "[includeIf \"gitdir:foo/\"]path=bar6" >>.git/config && + echo "[test]six=6" >.git/bar6 && + echo 6 >expect && + test-config read_early_config test.six >actual && + test_cmp expect actual + ) +' + test_expect_success SYMLINKS 'conditional include, set up symlinked $HOME' ' mkdir real-home && ln -s real-home home && diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh index b97357b8ab..1af8c454cf 100755 --- a/t/t1309-early-config.sh +++ b/t/t1309-early-config.sh @@ -47,6 +47,24 @@ test_expect_success 'ceiling #2' ' test xdg = "$(cat output)" ' +cmdline_config="'test.source=cmdline'" +test_expect_success 'read config file in right order' ' + echo "[test]source = home" >>.gitconfig && + git init foo && + ( + cd foo && + echo "[test]source = repo" >>.git/config && + GIT_CONFIG_PARAMETERS=$cmdline_config test-config \ + read_early_config test.source >actual && + cat >expected <<-\EOF && + home + repo + cmdline + EOF + test_cmp expected actual + ) +' + test_with_config () { rm -rf throwaway && git init throwaway && |