Skip to content

Commit 92bca22

Browse files
matheustavaresgitster
authored andcommitted
config: correctly read worktree configs in submodules
One of the steps in do_git_config_sequence() is to load the worktree-specific config file. Although the function receives a git_dir string, it relies on git_pathdup(), which uses the_repository->git_dir, to make the path to the file. Furthermore, it also checks that extensions.worktreeConfig is set through the repository_format_worktree_config variable, which refers to the_repository only. Thus, when a submodule has worktree-specific settings, a command executed in the superproject that recurses into the submodule won't find the said settings. This will be especially important in the next patch: git-grep will learn to honor sparse checkouts and, when running with --recurse-submodules, the submodule's sparse checkout settings must be loaded. As these settings are stored in the config.worktree file, they would be ignored without this patch. So let's fix this by reading the right config.worktree file and extensions.worktreeConfig setting, based on the git_dir and commondir paths given to do_git_config_sequence(). Also add a test to avoid any regressions. Signed-off-by: Matheus Tavares <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a2371e3 commit 92bca22

File tree

3 files changed

+91
-13
lines changed

3 files changed

+91
-13
lines changed

config.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,11 +1747,22 @@ static int do_git_config_sequence(const struct config_options *opts,
17471747
ret += git_config_from_file(fn, repo_config, data);
17481748

17491749
current_parsing_scope = CONFIG_SCOPE_WORKTREE;
1750-
if (!opts->ignore_worktree && repository_format_worktree_config) {
1751-
char *path = git_pathdup("config.worktree");
1752-
if (!access_or_die(path, R_OK, 0))
1753-
ret += git_config_from_file(fn, path, data);
1754-
free(path);
1750+
if (!opts->ignore_worktree && repo_config && opts->git_dir) {
1751+
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
1752+
struct strbuf buf = STRBUF_INIT;
1753+
1754+
read_repository_format(&repo_fmt, repo_config);
1755+
1756+
if (!verify_repository_format(&repo_fmt, &buf) &&
1757+
repo_fmt.worktree_config) {
1758+
char *path = mkpathdup("%s/config.worktree", opts->git_dir);
1759+
if (!access_or_die(path, R_OK, 0))
1760+
ret += git_config_from_file(fn, path, data);
1761+
free(path);
1762+
}
1763+
1764+
strbuf_release(&buf);
1765+
clear_repository_format(&repo_fmt);
17551766
}
17561767

17571768
current_parsing_scope = CONFIG_SCOPE_COMMAND;

t/helper/test-config.c

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
#include "cache.h"
33
#include "config.h"
44
#include "string-list.h"
5+
#include "submodule-config.h"
56

67
/*
78
* This program exposes the C API of the configuration mechanism
89
* as a set of simple commands in order to facilitate testing.
910
*
10-
* Reads stdin and prints result of command to stdout:
11+
* Usage: test-tool config [--submodule=<path>] <cmd> [<args>]
12+
*
13+
* If --submodule=<path> is given, <cmd> will operate on the submodule at the
14+
* given <path>. This option is not valid for the commands: read_early_config,
15+
* configset_get_value and configset_get_value_multi.
16+
*
17+
* Possible cmds are:
1118
*
1219
* get_value -> prints the value with highest priority for the entered key
1320
*
@@ -86,23 +93,51 @@ int cmd__config(int argc, const char **argv)
8693
const struct string_list *strptr;
8794
struct config_set cs = { .hash_initialized = 0 };
8895
enum test_config_exit_code ret = TC_SUCCESS;
96+
struct repository *repo = the_repository;
97+
const char *subrepo_path = NULL;
8998

9099
argc--; /* skip over "config" */
91100
argv++;
92101

93102
if (argc == 0)
94103
goto print_usage_error;
95104

105+
if (skip_prefix(*argv, "--submodule=", &subrepo_path)) {
106+
argc--;
107+
argv++;
108+
if (argc == 0)
109+
goto print_usage_error;
110+
}
111+
96112
if (argc == 2 && !strcmp(argv[0], "read_early_config")) {
113+
if (subrepo_path) {
114+
fprintf(stderr, "Cannot use --submodule with read_early_config\n");
115+
return TC_USAGE_ERROR;
116+
}
97117
read_early_config(early_config_cb, (void *)argv[1]);
98118
return TC_SUCCESS;
99119
}
100120

101121
setup_git_directory();
102122
git_configset_init(&cs);
103123

124+
if (subrepo_path) {
125+
const struct submodule *sub;
126+
struct repository *subrepo = xcalloc(1, sizeof(*repo));
127+
128+
sub = submodule_from_path(the_repository, &null_oid, subrepo_path);
129+
if (!sub || repo_submodule_init(subrepo, the_repository, sub)) {
130+
fprintf(stderr, "Invalid argument to --submodule: '%s'\n",
131+
subrepo_path);
132+
free(subrepo);
133+
ret = TC_USAGE_ERROR;
134+
goto out;
135+
}
136+
repo = subrepo;
137+
}
138+
104139
if (argc == 2 && !strcmp(argv[0], "get_value")) {
105-
if (!git_config_get_value(argv[1], &v)) {
140+
if (!repo_config_get_value(repo, argv[1], &v)) {
106141
if (!v)
107142
printf("(NULL)\n");
108143
else
@@ -112,7 +147,7 @@ int cmd__config(int argc, const char **argv)
112147
ret = TC_VALUE_NOT_FOUND;
113148
}
114149
} else if (argc == 2 && !strcmp(argv[0], "get_value_multi")) {
115-
strptr = git_config_get_value_multi(argv[1]);
150+
strptr = repo_config_get_value_multi(repo, argv[1]);
116151
if (strptr) {
117152
for (i = 0; i < strptr->nr; i++) {
118153
v = strptr->items[i].string;
@@ -126,27 +161,33 @@ int cmd__config(int argc, const char **argv)
126161
ret = TC_VALUE_NOT_FOUND;
127162
}
128163
} else if (argc == 2 && !strcmp(argv[0], "get_int")) {
129-
if (!git_config_get_int(argv[1], &val)) {
164+
if (!repo_config_get_int(repo, argv[1], &val)) {
130165
printf("%d\n", val);
131166
} else {
132167
printf("Value not found for \"%s\"\n", argv[1]);
133168
ret = TC_VALUE_NOT_FOUND;
134169
}
135170
} else if (argc == 2 && !strcmp(argv[0], "get_bool")) {
136-
if (!git_config_get_bool(argv[1], &val)) {
171+
if (!repo_config_get_bool(repo, argv[1], &val)) {
137172
printf("%d\n", val);
138173
} else {
174+
139175
printf("Value not found for \"%s\"\n", argv[1]);
140176
ret = TC_VALUE_NOT_FOUND;
141177
}
142178
} else if (argc == 2 && !strcmp(argv[0], "get_string")) {
143-
if (!git_config_get_string_const(argv[1], &v)) {
179+
if (!repo_config_get_string_const(repo, argv[1], &v)) {
144180
printf("%s\n", v);
145181
} else {
146182
printf("Value not found for \"%s\"\n", argv[1]);
147183
ret = TC_VALUE_NOT_FOUND;
148184
}
149185
} else if (argc >= 2 && !strcmp(argv[0], "configset_get_value")) {
186+
if (subrepo_path) {
187+
fprintf(stderr, "Cannot use --submodule with configset_get_value\n");
188+
ret = TC_USAGE_ERROR;
189+
goto out;
190+
}
150191
for (i = 2; i < argc; i++) {
151192
int err;
152193
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ -165,6 +206,11 @@ int cmd__config(int argc, const char **argv)
165206
ret = TC_VALUE_NOT_FOUND;
166207
}
167208
} else if (argc >= 2 && !strcmp(argv[0], "configset_get_value_multi")) {
209+
if (subrepo_path) {
210+
fprintf(stderr, "Cannot use --submodule with configset_get_value_multi\n");
211+
ret = TC_USAGE_ERROR;
212+
goto out;
213+
}
168214
for (i = 2; i < argc; i++) {
169215
int err;
170216
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ -187,14 +233,19 @@ int cmd__config(int argc, const char **argv)
187233
ret = TC_VALUE_NOT_FOUND;
188234
}
189235
} else if (!strcmp(argv[0], "iterate")) {
190-
git_config(iterate_cb, NULL);
236+
repo_config(repo, iterate_cb, NULL);
191237
} else {
192238
print_usage_error:
193-
fprintf(stderr, "Invalid syntax. Usage: test-tool config <cmd> [args]\n");
239+
fprintf(stderr, "Invalid syntax. Usage: test-tool config"
240+
" [--submodule=<path>] <cmd> [args]\n");
194241
ret = TC_USAGE_ERROR;
195242
}
196243

197244
out:
198245
git_configset_clear(&cs);
246+
if (repo != the_repository) {
247+
repo_clear(repo);
248+
free(repo);
249+
}
199250
return ret;
200251
}

t/t2404-worktree-config.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,20 @@ test_expect_success 'config.worktree no longer read without extension' '
7676
test_cmp_config -C wt2 shared this.is
7777
'
7878

79+
test_expect_success 'correctly read config.worktree from submodules' '
80+
test_unconfig extensions.worktreeConfig &&
81+
git init sub &&
82+
(
83+
cd sub &&
84+
test_commit A &&
85+
git config extensions.worktreeConfig true &&
86+
git config --worktree wtconfig.sub test-value
87+
) &&
88+
git submodule add ./sub &&
89+
git commit -m "add sub" &&
90+
echo test-value >expect &&
91+
test-tool config --submodule=sub get_value wtconfig.sub >actual &&
92+
test_cmp expect actual
93+
'
94+
7995
test_done

0 commit comments

Comments
 (0)