Skip to content

Commit e145a0b

Browse files
pcloudsgitster
authored andcommitted
config: correct file reading order in read_early_config()
Config file reading order is important because each file can override values in the previous files and this is expected behavior. Normally we read in this order, all in do_git_config_sequence(): 1. $HOME/.gitconfig 2. $GIT_DIR/config 3. config from command line However in read_early_config() the order may be swapped a bit if setup_git_directory() has not been called: 1. $HOME/.gitconfig 2. $GIT_DIR/config is NOT read because .git dir is not found _yet_ 3. config from command line 4. $GIT_DIR/config is now READ (after discover_git_directory() call) The reading at step 4 could override config at step 3, which is not the expectation. Now that we could pass the .git dir around, we could feed discover_git_directory() back to step 2, so that it works again, and remove step 4. Noticed-by: Jeff King <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2185fde commit e145a0b

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

config.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,12 +1504,20 @@ int git_config_system(void)
15041504
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
15051505
}
15061506

1507-
static int do_git_config_sequence(config_fn_t fn, void *data)
1507+
static int do_git_config_sequence(const struct config_options *opts,
1508+
config_fn_t fn, void *data)
15081509
{
15091510
int ret = 0;
15101511
char *xdg_config = xdg_config_home("config");
15111512
char *user_config = expand_user_path("~/.gitconfig");
1512-
char *repo_config = have_git_dir() ? git_pathdup("config") : NULL;
1513+
char *repo_config;
1514+
1515+
if (opts->git_dir)
1516+
repo_config = mkpathdup("%s/config", opts->git_dir);
1517+
else if (have_git_dir())
1518+
repo_config = git_pathdup("config");
1519+
else
1520+
repo_config = NULL;
15131521

15141522
current_parsing_scope = CONFIG_SCOPE_SYSTEM;
15151523
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
@@ -1563,7 +1571,7 @@ int git_config_with_options(config_fn_t fn, void *data,
15631571
else if (config_source && config_source->blob)
15641572
return git_config_from_blob_ref(fn, config_source->blob, data);
15651573

1566-
return do_git_config_sequence(fn, data);
1574+
return do_git_config_sequence(opts, fn, data);
15671575
}
15681576

15691577
static void git_config_raw(config_fn_t fn, void *data)
@@ -1613,7 +1621,6 @@ void read_early_config(config_fn_t cb, void *data)
16131621
{
16141622
struct config_options opts = {0};
16151623
struct strbuf buf = STRBUF_INIT;
1616-
char *to_free = NULL;
16171624

16181625
opts.respect_includes = 1;
16191626

@@ -1628,20 +1635,11 @@ void read_early_config(config_fn_t cb, void *data)
16281635
* call).
16291636
*/
16301637
else if (discover_git_directory(&buf))
1631-
opts.git_dir = to_free = xstrdup(buf.buf);
1638+
opts.git_dir = buf.buf;
16321639

16331640
git_config_with_options(cb, data, NULL, &opts);
16341641

1635-
if (!have_git_dir() && opts.git_dir) {
1636-
struct git_config_source repo_config;
1637-
1638-
memset(&repo_config, 0, sizeof(repo_config));
1639-
strbuf_addstr(&buf, "/config");
1640-
repo_config.file = buf.buf;
1641-
git_config_with_options(cb, data, &repo_config, &opts);
1642-
}
16431642
strbuf_release(&buf);
1644-
free(to_free);
16451643
}
16461644

16471645
static void git_config_check_init(void);

t/t1309-early-config.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@ test_expect_success 'ceiling #2' '
4747
test xdg = "$(cat output)"
4848
'
4949

50+
cmdline_config="'test.source=cmdline'"
51+
test_expect_success 'read config file in right order' '
52+
echo "[test]source = home" >>.gitconfig &&
53+
git init foo &&
54+
(
55+
cd foo &&
56+
echo "[test]source = repo" >>.git/config &&
57+
GIT_CONFIG_PARAMETERS=$cmdline_config test-config \
58+
read_early_config test.source >actual &&
59+
cat >expected <<-\EOF &&
60+
home
61+
repo
62+
cmdline
63+
EOF
64+
test_cmp expected actual
65+
)
66+
'
67+
5068
test_with_config () {
5169
rm -rf throwaway &&
5270
git init throwaway &&

0 commit comments

Comments
 (0)