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 "editor.h"
#include "environment.h"
#include "repository.h"
#include "gettext.h"
#include "ident.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;
} else if (use_worktree_config) {
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");
else if (worktrees[0] && worktrees[1])
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
* 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);
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,
const struct config_options *opts,
const struct repository *repo,
config_fn_t fn, void *data)
{
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);
if (!opts->ignore_worktree && worktree_config &&
repository_format_worktree_config &&
repo && repo->repository_format_worktree_config &&
!access_or_die(worktree_config, R_OK, 0)) {
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,
data);
} 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) {
@@ -3339,7 +3340,7 @@ int repo_config_set_worktree_gently(struct repository *r,
const char *key, const char *value)
{
/* 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");
int ret = git_config_set_multivar_in_file_gently(
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_on_object_refname_ambiguity = 1;
int repository_format_precious_objects;
int repository_format_worktree_config;
const char *git_commit_encoding;
const char *git_log_output_encoding;
char *apply_default_whitespace;

View File

@@ -197,7 +197,6 @@ extern char *notes_ref_name;
extern int grafts_replace_parents;
extern int repository_format_precious_objects;
extern int repository_format_worktree_config;
/*
* 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;
repo_set_hash_algo(repo, format.hash_algo);
repo->repository_format_worktree_config = format.worktree_config;
/* take ownership of 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;
/* Configurations */
int repository_format_worktree_config;
/* Indicate if a repository has a different 'commondir' from 'gitdir' */
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_worktree_config = candidate->worktree_config;
string_list_clear(&candidate->unknown_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
* config if present
@@ -1423,6 +1422,9 @@ int discover_git_directory(struct strbuf *commondir,
return -1;
}
the_repository->repository_format_worktree_config =
candidate.worktree_config;
/* take ownership of candidate.partial_clone */
the_repository->repository_format_partial_clone =
candidate.partial_clone;
@@ -1560,6 +1562,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
if (startup_info->have_repository) {
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 */
the_repository->repository_format_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);
startup_info->have_repository = 1;
repo_set_hash_algo(the_repository, fmt->hash_algo);
the_repository->repository_format_worktree_config =
fmt->worktree_config;
the_repository->repository_format_partial_clone =
xstrdup_or_null(fmt->partial_clone);
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 --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 &&
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_expect_success "--recurse-submodules and $1 are incompatible" "
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
* upgrade process.
*/
if (repository_format_worktree_config)
if (r->repository_format_worktree_config)
return 0;
if ((res = git_config_set_gently("extensions.worktreeConfig", "true")))
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
* of the current process.
*/
repository_format_worktree_config = 1;
r->repository_format_worktree_config = 1;
cleanup:
git_configset_clear(&cs);