repository: move 'repository_format_worktree_config' to repo scope

Move 'repository_format_worktree_config' out of the global scope and into the 'repository' struct. This change is similar to how 'repository_format_partial_clone' was moved in ebaf3bcf1ae (repository: move global r_f_p_c to repo struct, 2021-06-17), adding it to the 'repository' struct and updating 'setup.c' & 'repository.c' functions to assign the value appropriately. The primary goal of this change is to be able to load the worktree config of a submodule depending on whether that submodule - not its superproject - has 'extensions.worktreeConfig' enabled. To ensure 'do_git_config_sequence()' has access to the newly repo-scoped configuration, add a 'struct repository' argument to 'do_git_config_sequence()' and pass it the 'repo' value from 'config_with_options()'. Finally, add/update tests in 't3007-ls-files-recurse-submodules.sh' to verify 'extensions.worktreeConfig' is read an used independently by superprojects and submodules. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Victoria Dye committed May 26, 2023 at 01:33 UTC 3867f6d650c89230ae7393e2d57160ccc14758c7
10 files changed +38 -15
builtin/config.c
+2 -1
@@ -5,6 +5,7 @@
5 #include "color.h"
6 #include "editor.h"
7 #include "environment.h"
8 +#include "repository.h"
9 #include "gettext.h"
10 #include "ident.h"
11 #include "parse-options.h"
@@ -717,7 +718,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
718 given_config_source.scope = CONFIG_SCOPE_LOCAL;
719 } else if (use_worktree_config) {
720 struct worktree **worktrees = get_worktrees();
720 - if (repository_format_worktree_config)
721 + if (the_repository->repository_format_worktree_config)
722 given_config_source.file = git_pathdup("config.worktree");
723 else if (worktrees[0] && worktrees[1])
724 die(_("--worktree cannot be used with multiple "
builtin/worktree.c
+1 -1
@@ -483,7 +483,7 @@ static int add_worktree(const char *path, const char *refname,
483 * values from the current worktree into the new one, that way the
484 * new worktree behaves the same as this one.
485 */
486 - if (repository_format_worktree_config)
486 + if (the_repository->repository_format_worktree_config)
487 copy_filtered_worktree_config(sb_repo.buf);
488
489 strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
config.c
+4 -3
@@ -2195,6 +2195,7 @@ int git_config_system(void)
2195
2196 static int do_git_config_sequence(struct config_reader *reader,
2197 const struct config_options *opts,
2198 + const struct repository *repo,
2199 config_fn_t fn, void *data)
2200 {
2201 int ret = 0;
@@ -2243,7 +2244,7 @@ static int do_git_config_sequence(struct config_reader *reader,
2244
2245 config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE);
2246 if (!opts->ignore_worktree && worktree_config &&
2246 - repository_format_worktree_config &&
2247 + repo && repo->repository_format_worktree_config &&
2248 !access_or_die(worktree_config, R_OK, 0)) {
2249 ret += git_config_from_file(fn, worktree_config, data);
2250 }
@@ -2296,7 +2297,7 @@ int config_with_options(config_fn_t fn, void *data,
2297 ret = git_config_from_blob_ref(fn, repo, config_source->blob,
2298 data);
2299 } else {
2299 - ret = do_git_config_sequence(&the_reader, opts, fn, data);
2300 + ret = do_git_config_sequence(&the_reader, opts, repo, fn, data);
2301 }
2302
2303 if (inc.remote_urls) {
@@ -3339,7 +3340,7 @@ int repo_config_set_worktree_gently(struct repository *r,
3340 const char *key, const char *value)
3341 {
3342 /* Only use worktree-specific config if it is already enabled. */
3342 - if (repository_format_worktree_config) {
3343 + if (r->repository_format_worktree_config) {
3344 char *file = repo_git_path(r, "config.worktree");
3345 int ret = git_config_set_multivar_in_file_gently(
3346 file, key, value, NULL, 0);
environment.c
-1
@@ -42,7 +42,6 @@ int is_bare_repository_cfg = -1; /* unspecified */
42 int warn_ambiguous_refs = 1;
43 int warn_on_object_refname_ambiguity = 1;
44 int repository_format_precious_objects;
45 -int repository_format_worktree_config;
45 const char *git_commit_encoding;
46 const char *git_log_output_encoding;
47 char *apply_default_whitespace;
environment.h
-1
@@ -197,7 +197,6 @@ extern char *notes_ref_name;
197 extern int grafts_replace_parents;
198
199 extern int repository_format_precious_objects;
200 -extern int repository_format_worktree_config;
200
201 /*
202 * Create a temporary file rooted in the object database directory, or
repository.c
+1
@@ -182,6 +182,7 @@ int repo_init(struct repository *repo,
182 goto error;
183
184 repo_set_hash_algo(repo, format.hash_algo);
185 + repo->repository_format_worktree_config = format.worktree_config;
186
187 /* take ownership of format.partial_clone */
188 repo->repository_format_partial_clone = format.partial_clone;
repository.h
+1
@@ -163,6 +163,7 @@ struct repository {
163 struct promisor_remote_config *promisor_remote_config;
164
165 /* Configurations */
166 + int repository_format_worktree_config;
167
168 /* Indicate if a repository has a different 'commondir' from 'gitdir' */
169 unsigned different_commondir:1;
setup.c
+8 -2
@@ -650,11 +650,10 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
650 }
651
652 repository_format_precious_objects = candidate->precious_objects;
653 - repository_format_worktree_config = candidate->worktree_config;
653 string_list_clear(&candidate->unknown_extensions, 0);
654 string_list_clear(&candidate->v1_only_extensions, 0);
655
657 - if (repository_format_worktree_config) {
656 + if (candidate->worktree_config) {
657 /*
658 * pick up core.bare and core.worktree from per-worktree
659 * config if present
@@ -1423,6 +1422,9 @@ int discover_git_directory(struct strbuf *commondir,
1422 return -1;
1423 }
1424
1425 + the_repository->repository_format_worktree_config =
1426 + candidate.worktree_config;
1427 +
1428 /* take ownership of candidate.partial_clone */
1429 the_repository->repository_format_partial_clone =
1430 candidate.partial_clone;
@@ -1560,6 +1562,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
1562 }
1563 if (startup_info->have_repository) {
1564 repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
1565 + the_repository->repository_format_worktree_config =
1566 + repo_fmt.worktree_config;
1567 /* take ownership of repo_fmt.partial_clone */
1568 the_repository->repository_format_partial_clone =
1569 repo_fmt.partial_clone;
@@ -1651,6 +1655,8 @@ void check_repository_format(struct repository_format *fmt)
1655 check_repository_format_gently(get_git_dir(), fmt, NULL);
1656 startup_info->have_repository = 1;
1657 repo_set_hash_algo(the_repository, fmt->hash_algo);
1658 + the_repository->repository_format_worktree_config =
1659 + fmt->worktree_config;
1660 the_repository->repository_format_partial_clone =
1661 xstrdup_or_null(fmt->partial_clone);
1662 clear_repository_format(&repo_fmt);
t/t3007-ls-files-recurse-submodules.sh
+19 -4
@@ -309,14 +309,29 @@ test_expect_success '--recurse-submodules parses submodule worktree config' '
309 test_config -C submodule extensions.worktreeConfig true &&
310 test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
311
312 - # NEEDSWORK: the extensions.worktreeConfig is set globally based on
313 - # superproject, so we need to enable it in the superproject.
314 - test_config extensions.worktreeConfig true &&
315 -
312 test_must_fail git ls-files --recurse-submodules 2>err &&
313 grep "bad boolean config value" err
314 '
315
316 +test_expect_success '--recurse-submodules submodules ignore super project worktreeConfig extension' '
317 + # Enable worktree config in both super project & submodule, set an
318 + # invalid config in the submodule worktree config
319 + test_config extensions.worktreeConfig true &&
320 + test_config -C submodule extensions.worktreeConfig true &&
321 + test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
322 +
323 + # Now, disable the worktree config in the submodule. Note that we need
324 + # to manually re-enable extensions.worktreeConfig when the test is
325 + # finished, otherwise the test_unconfig of index.sparse will not work.
326 + test_unconfig -C submodule extensions.worktreeConfig &&
327 + test_when_finished "git -C submodule config extensions.worktreeConfig true" &&
328 +
329 + # With extensions.worktreeConfig disabled in the submodule, the invalid
330 + # worktree config is not picked up.
331 + git ls-files --recurse-submodules 2>err &&
332 + ! grep "bad boolean config value" err
333 +'
334 +
335 test_incompatible_with_recurse_submodules () {
336 test_expect_success "--recurse-submodules and $1 are incompatible" "
337 test_must_fail git ls-files --recurse-submodules $1 2>actual &&
worktree.c
+2 -2
@@ -806,7 +806,7 @@ int init_worktree_config(struct repository *r)
806 * If the extension is already enabled, then we can skip the
807 * upgrade process.
808 */
809 - if (repository_format_worktree_config)
809 + if (r->repository_format_worktree_config)
810 return 0;
811 if ((res = git_config_set_gently("extensions.worktreeConfig", "true")))
812 return error(_("failed to set extensions.worktreeConfig setting"));
@@ -846,7 +846,7 @@ int init_worktree_config(struct repository *r)
846 * Ensure that we use worktree config for the remaining lifetime
847 * of the current process.
848 */
849 - repository_format_worktree_config = 1;
849 + r->repository_format_worktree_config = 1;
850
851 cleanup:
852 git_configset_clear(&cs);