Skip to content

Commit ec9e7cd

Browse files
committed
config: read from config sequence for global scope
The output of `git config list --global` should include both `$HOME/.gitconfig` and `$XDG_CONFIG_HOME/git/config`, but it only reads from the former. We've assumed each config scope corresponds to a single config file location. Because of this assumption, `git config list --global` reads the global config by calling `git_config_from_file_with_options(..., "~/.gitconfig", ...)`. This function usage restricts us to a single source file. Since the global scope includes more than one file, we should use another method to read the global config. The output of `git config list --show-scope --show-origin` correctly includes both the home and XDG config files. So there's existing code that respects both locations, namely the `do_git_config_sequence()` function which reads from all scopes. Introduce flags that make it possible to ignore all but the global scope (i.e. ignore system, local, worktree, cmdline). Then, reuse this function for reading only the global scope. This was the suggested solution in the original bug report thread [1]. Note 1: The `ignore_global` flag is not set anywhere, so the `if (!opts->ignore_global)` condition is always met. We can remove this flag if desired. Note 2: It's assumed that `config_source->scope == CONFIG_SCOPE_GLOBAL` iff `--global` is specified. This comparison determines whether to call `do_git_config_sequence()` for the global scope, or to keep calling `git_config_from_file_with_options()` for other scopes. Note 3: Keep populating `opts->source.file` in `builtin/config.c` because it is used as the destination file for write operations. The proposed changes could convolute the code because there is no single source of truth for the config file locations in the global scope. Add a comment to help clarify this. Please let me know if it's unclear. [1]: https://lore.kernel.org/git/[email protected]. Reported-by: Jade Lovelace <[email protected]> Suggested-by: Glen Choo <[email protected]> Signed-off-by: Delilah Ashley Wu <[email protected]>
1 parent f28d131 commit ec9e7cd

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

builtin/config.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,18 @@ static void location_options_init(struct config_location_options *opts,
768768
}
769769

770770
if (opts->use_global_config) {
771+
/*
772+
* Reading config is handled by `config.c#do_git_config_sequence()`
773+
* because the global config can be sourced from multiple files.
774+
* Writing config should point to a single destination as set in
775+
* `opts->source.file` below.
776+
*/
777+
opts->options.ignore_repo = 1;
778+
opts->options.ignore_cmdline= 1;
779+
opts->options.ignore_worktree = 1;
780+
opts->options.ignore_system = 1;
781+
opts->source.scope = CONFIG_SCOPE_GLOBAL;
782+
771783
opts->source.file = opts->file_to_free = git_global_config();
772784
if (!opts->source.file)
773785
/*

config.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,22 +2040,27 @@ static int do_git_config_sequence(const struct config_options *opts,
20402040
worktree_config = NULL;
20412041
}
20422042

2043-
if (git_config_system() && system_config &&
2043+
if (!opts->ignore_system && git_config_system() && system_config &&
20442044
!access_or_die(system_config, R_OK,
20452045
opts->system_gently ? ACCESS_EACCES_OK : 0))
20462046
ret += git_config_from_file_with_options(fn, system_config,
20472047
data, CONFIG_SCOPE_SYSTEM,
20482048
NULL);
20492049

2050-
git_global_config_paths(&user_config, &xdg_config);
2050+
if (!opts->ignore_global) {
2051+
git_global_config_paths(&user_config, &xdg_config);
2052+
2053+
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
2054+
ret += git_config_from_file_with_options(fn, xdg_config, data,
2055+
CONFIG_SCOPE_GLOBAL, NULL);
20512056

2052-
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))
2053-
ret += git_config_from_file_with_options(fn, xdg_config, data,
2054-
CONFIG_SCOPE_GLOBAL, NULL);
2057+
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
2058+
ret += git_config_from_file_with_options(fn, user_config, data,
2059+
CONFIG_SCOPE_GLOBAL, NULL);
20552060

2056-
if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
2057-
ret += git_config_from_file_with_options(fn, user_config, data,
2058-
CONFIG_SCOPE_GLOBAL, NULL);
2061+
free(xdg_config);
2062+
free(user_config);
2063+
}
20592064

20602065
if (!opts->ignore_repo && repo_config &&
20612066
!access_or_die(repo_config, R_OK, 0))
@@ -2074,8 +2079,6 @@ static int do_git_config_sequence(const struct config_options *opts,
20742079
die(_("unable to parse command-line config"));
20752080

20762081
free(system_config);
2077-
free(xdg_config);
2078-
free(user_config);
20792082
free(repo_config);
20802083
free(worktree_config);
20812084
return ret;
@@ -2105,7 +2108,8 @@ int config_with_options(config_fn_t fn, void *data,
21052108
*/
21062109
if (config_source && config_source->use_stdin) {
21072110
ret = git_config_from_stdin(fn, data, config_source->scope);
2108-
} else if (config_source && config_source->file) {
2111+
} else if (config_source && config_source->file &&
2112+
config_source->scope != CONFIG_SCOPE_GLOBAL) {
21092113
ret = git_config_from_file_with_options(fn, config_source->file,
21102114
data, config_source->scope,
21112115
NULL);

config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ typedef int (*config_parser_event_fn_t)(enum config_event_t type,
8787

8888
struct config_options {
8989
unsigned int respect_includes : 1;
90+
unsigned int ignore_system : 1; // From /etc/gitconfig
91+
unsigned int ignore_global : 1; // From a combination of `~/.gitconfig` and `XDG_CONFIG_HOME/git/config`
9092
unsigned int ignore_repo : 1;
9193
unsigned int ignore_worktree : 1;
9294
unsigned int ignore_cmdline : 1;

0 commit comments

Comments
 (0)