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 ebaf3bcf1a (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>
This commit is contained in:
Victoria Dye
2023-05-26 01:33:00 +00:00
committed by Junio C Hamano
parent 9b6b06c159
commit 3867f6d650
10 changed files with 38 additions and 15 deletions

View File

@@ -5,6 +5,7 @@
#include "color.h" #include "color.h"
#include "editor.h" #include "editor.h"
#include "environment.h" #include "environment.h"
#include "repository.h"
#include "gettext.h" #include "gettext.h"
#include "ident.h" #include "ident.h"
#include "parse-options.h" #include "parse-options.h"
@@ -717,7 +718,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
given_config_source.scope = CONFIG_SCOPE_LOCAL; given_config_source.scope = CONFIG_SCOPE_LOCAL;
} else if (use_worktree_config) { } else if (use_worktree_config) {
struct worktree **worktrees = get_worktrees(); struct worktree **worktrees = get_worktrees();
if (repository_format_worktree_config) if (the_repository->repository_format_worktree_config)
given_config_source.file = git_pathdup("config.worktree"); given_config_source.file = git_pathdup("config.worktree");
else if (worktrees[0] && worktrees[1]) else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple " die(_("--worktree cannot be used with multiple "

View File

@@ -483,7 +483,7 @@ static int add_worktree(const char *path, const char *refname,
* values from the current worktree into the new one, that way the * values from the current worktree into the new one, that way the
* new worktree behaves the same as this one. * new worktree behaves the same as this one.
*/ */
if (repository_format_worktree_config) if (the_repository->repository_format_worktree_config)
copy_filtered_worktree_config(sb_repo.buf); copy_filtered_worktree_config(sb_repo.buf);
strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf); strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);

View File

@@ -2195,6 +2195,7 @@ int git_config_system(void)
static int do_git_config_sequence(struct config_reader *reader, static int do_git_config_sequence(struct config_reader *reader,
const struct config_options *opts, const struct config_options *opts,
const struct repository *repo,
config_fn_t fn, void *data) config_fn_t fn, void *data)
{ {
int ret = 0; int ret = 0;
@@ -2243,7 +2244,7 @@ static int do_git_config_sequence(struct config_reader *reader,
config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE); config_reader_set_scope(reader, CONFIG_SCOPE_WORKTREE);
if (!opts->ignore_worktree && worktree_config && if (!opts->ignore_worktree && worktree_config &&
repository_format_worktree_config && repo && repo->repository_format_worktree_config &&
!access_or_die(worktree_config, R_OK, 0)) { !access_or_die(worktree_config, R_OK, 0)) {
ret += git_config_from_file(fn, worktree_config, data); ret += git_config_from_file(fn, worktree_config, data);
} }
@@ -2296,7 +2297,7 @@ int config_with_options(config_fn_t fn, void *data,
ret = git_config_from_blob_ref(fn, repo, config_source->blob, ret = git_config_from_blob_ref(fn, repo, config_source->blob,
data); data);
} else { } else {
ret = do_git_config_sequence(&the_reader, opts, fn, data); ret = do_git_config_sequence(&the_reader, opts, repo, fn, data);
} }
if (inc.remote_urls) { if (inc.remote_urls) {
@@ -3339,7 +3340,7 @@ int repo_config_set_worktree_gently(struct repository *r,
const char *key, const char *value) const char *key, const char *value)
{ {
/* Only use worktree-specific config if it is already enabled. */ /* Only use worktree-specific config if it is already enabled. */
if (repository_format_worktree_config) { if (r->repository_format_worktree_config) {
char *file = repo_git_path(r, "config.worktree"); char *file = repo_git_path(r, "config.worktree");
int ret = git_config_set_multivar_in_file_gently( int ret = git_config_set_multivar_in_file_gently(
file, key, value, NULL, 0); file, key, value, NULL, 0);

View File

@@ -42,7 +42,6 @@ int is_bare_repository_cfg = -1; /* unspecified */
int warn_ambiguous_refs = 1; int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1; int warn_on_object_refname_ambiguity = 1;
int repository_format_precious_objects; int repository_format_precious_objects;
int repository_format_worktree_config;
const char *git_commit_encoding; const char *git_commit_encoding;
const char *git_log_output_encoding; const char *git_log_output_encoding;
char *apply_default_whitespace; char *apply_default_whitespace;

View File

@@ -197,7 +197,6 @@ extern char *notes_ref_name;
extern int grafts_replace_parents; extern int grafts_replace_parents;
extern int repository_format_precious_objects; extern int repository_format_precious_objects;
extern int repository_format_worktree_config;
/* /*
* Create a temporary file rooted in the object database directory, or * Create a temporary file rooted in the object database directory, or

View File

@@ -182,6 +182,7 @@ int repo_init(struct repository *repo,
goto error; goto error;
repo_set_hash_algo(repo, format.hash_algo); repo_set_hash_algo(repo, format.hash_algo);
repo->repository_format_worktree_config = format.worktree_config;
/* take ownership of format.partial_clone */ /* take ownership of format.partial_clone */
repo->repository_format_partial_clone = format.partial_clone; repo->repository_format_partial_clone = format.partial_clone;

View File

@@ -163,6 +163,7 @@ struct repository {
struct promisor_remote_config *promisor_remote_config; struct promisor_remote_config *promisor_remote_config;
/* Configurations */ /* Configurations */
int repository_format_worktree_config;
/* Indicate if a repository has a different 'commondir' from 'gitdir' */ /* Indicate if a repository has a different 'commondir' from 'gitdir' */
unsigned different_commondir:1; unsigned different_commondir:1;

10
setup.c
View File

@@ -650,11 +650,10 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
} }
repository_format_precious_objects = candidate->precious_objects; repository_format_precious_objects = candidate->precious_objects;
repository_format_worktree_config = candidate->worktree_config;
string_list_clear(&candidate->unknown_extensions, 0); string_list_clear(&candidate->unknown_extensions, 0);
string_list_clear(&candidate->v1_only_extensions, 0); string_list_clear(&candidate->v1_only_extensions, 0);
if (repository_format_worktree_config) { if (candidate->worktree_config) {
/* /*
* pick up core.bare and core.worktree from per-worktree * pick up core.bare and core.worktree from per-worktree
* config if present * config if present
@@ -1423,6 +1422,9 @@ int discover_git_directory(struct strbuf *commondir,
return -1; return -1;
} }
the_repository->repository_format_worktree_config =
candidate.worktree_config;
/* take ownership of candidate.partial_clone */ /* take ownership of candidate.partial_clone */
the_repository->repository_format_partial_clone = the_repository->repository_format_partial_clone =
candidate.partial_clone; candidate.partial_clone;
@@ -1560,6 +1562,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
} }
if (startup_info->have_repository) { if (startup_info->have_repository) {
repo_set_hash_algo(the_repository, repo_fmt.hash_algo); repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
the_repository->repository_format_worktree_config =
repo_fmt.worktree_config;
/* take ownership of repo_fmt.partial_clone */ /* take ownership of repo_fmt.partial_clone */
the_repository->repository_format_partial_clone = the_repository->repository_format_partial_clone =
repo_fmt.partial_clone; repo_fmt.partial_clone;
@@ -1651,6 +1655,8 @@ void check_repository_format(struct repository_format *fmt)
check_repository_format_gently(get_git_dir(), fmt, NULL); check_repository_format_gently(get_git_dir(), fmt, NULL);
startup_info->have_repository = 1; startup_info->have_repository = 1;
repo_set_hash_algo(the_repository, fmt->hash_algo); repo_set_hash_algo(the_repository, fmt->hash_algo);
the_repository->repository_format_worktree_config =
fmt->worktree_config;
the_repository->repository_format_partial_clone = the_repository->repository_format_partial_clone =
xstrdup_or_null(fmt->partial_clone); xstrdup_or_null(fmt->partial_clone);
clear_repository_format(&repo_fmt); clear_repository_format(&repo_fmt);

View File

@@ -309,14 +309,29 @@ test_expect_success '--recurse-submodules parses submodule worktree config' '
test_config -C submodule extensions.worktreeConfig true && test_config -C submodule extensions.worktreeConfig true &&
test_config -C submodule --worktree index.sparse "invalid non-boolean value" && test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
# NEEDSWORK: the extensions.worktreeConfig is set globally based on
# superproject, so we need to enable it in the superproject.
test_config extensions.worktreeConfig true &&
test_must_fail git ls-files --recurse-submodules 2>err && test_must_fail git ls-files --recurse-submodules 2>err &&
grep "bad boolean config value" err grep "bad boolean config value" err
' '
test_expect_success '--recurse-submodules submodules ignore super project worktreeConfig extension' '
# Enable worktree config in both super project & submodule, set an
# invalid config in the submodule worktree config
test_config extensions.worktreeConfig true &&
test_config -C submodule extensions.worktreeConfig true &&
test_config -C submodule --worktree index.sparse "invalid non-boolean value" &&
# Now, disable the worktree config in the submodule. Note that we need
# to manually re-enable extensions.worktreeConfig when the test is
# finished, otherwise the test_unconfig of index.sparse will not work.
test_unconfig -C submodule extensions.worktreeConfig &&
test_when_finished "git -C submodule config extensions.worktreeConfig true" &&
# With extensions.worktreeConfig disabled in the submodule, the invalid
# worktree config is not picked up.
git ls-files --recurse-submodules 2>err &&
! grep "bad boolean config value" err
'
test_incompatible_with_recurse_submodules () { test_incompatible_with_recurse_submodules () {
test_expect_success "--recurse-submodules and $1 are incompatible" " test_expect_success "--recurse-submodules and $1 are incompatible" "
test_must_fail git ls-files --recurse-submodules $1 2>actual && test_must_fail git ls-files --recurse-submodules $1 2>actual &&

View File

@@ -806,7 +806,7 @@ int init_worktree_config(struct repository *r)
* If the extension is already enabled, then we can skip the * If the extension is already enabled, then we can skip the
* upgrade process. * upgrade process.
*/ */
if (repository_format_worktree_config) if (r->repository_format_worktree_config)
return 0; return 0;
if ((res = git_config_set_gently("extensions.worktreeConfig", "true"))) if ((res = git_config_set_gently("extensions.worktreeConfig", "true")))
return error(_("failed to set extensions.worktreeConfig setting")); return error(_("failed to set extensions.worktreeConfig setting"));
@@ -846,7 +846,7 @@ int init_worktree_config(struct repository *r)
* Ensure that we use worktree config for the remaining lifetime * Ensure that we use worktree config for the remaining lifetime
* of the current process. * of the current process.
*/ */
repository_format_worktree_config = 1; r->repository_format_worktree_config = 1;
cleanup: cleanup:
git_configset_clear(&cs); git_configset_clear(&cs);