sparse-checkout: set worktree-config correctly

`git sparse-checkout set/init` enables worktree-specific
configuration[*] by setting extensions.worktreeConfig=true, but neglects
to perform the additional necessary bookkeeping of relocating
`core.bare=true` and `core.worktree` from $GIT_COMMON_DIR/config to
$GIT_COMMON_DIR/config.worktree, as documented in git-worktree.txt. As a
result of this oversight, these settings, which are nonsensical for
secondary worktrees, can cause Git commands to incorrectly consider a
worktree bare (in the case of `core.bare`) or operate on the wrong
worktree (in the case of `core.worktree`). Fix this problem by taking
advantage of the recently-added init_worktree_config() which enables
`extensions.worktreeConfig` and takes care of necessary bookkeeping.

While at it, for backward-compatibility reasons, also stop upgrading the
repository format to "1" since doing so is (unintentionally) not
required to take advantage of `extensions.worktreeConfig`, as explained
by 11664196ac ("Revert "check_repository_format_gently(): refuse
extensions for old repositories"", 2020-07-15).

[*] The main reason to use worktree-specific config for the
sparse-checkout builtin was to avoid enabling sparse-checkout patterns
in one and causing a loss of files in another. If a worktree does not
have a sparse-checkout patterns file, then the sparse-checkout logic
will not kick in on that worktree.

Reported-by: Sean Allred <allred.sean@gmail.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee
2022-02-07 21:33:01 +00:00
committed by Junio C Hamano
parent fe18733927
commit 7316dc5f6f
4 changed files with 30 additions and 28 deletions

View File

@ -31,13 +31,21 @@ COMMANDS
Describe the patterns in the sparse-checkout file. Describe the patterns in the sparse-checkout file.
'set':: 'set'::
Enable the necessary config settings Enable the necessary sparse-checkout config settings
(extensions.worktreeConfig, core.sparseCheckout, (`core.sparseCheckout`, `core.sparseCheckoutCone`, and
core.sparseCheckoutCone) if they are not already enabled, and `index.sparse`) if they are not already set to the desired values,
write a set of patterns to the sparse-checkout file from the and write a set of patterns to the sparse-checkout file from the
list of arguments following the 'set' subcommand. Update the list of arguments following the 'set' subcommand. Update the
working directory to match the new patterns. working directory to match the new patterns.
+ +
To ensure that adjusting the sparse-checkout settings within a worktree
does not alter the sparse-checkout settings in other worktrees, the 'set'
subcommand will upgrade your repository config to use worktree-specific
config if not already present. The sparsity defined by the arguments to
the 'set' subcommand are stored in the worktree-specific sparse-checkout
file. See linkgit:git-worktree[1] and the documentation of
`extensions.worktreeConfig` in linkgit:git-config[1] for more details.
+
When the `--stdin` option is provided, the patterns are read from When the `--stdin` option is provided, the patterns are read from
standard in as a newline-delimited list instead of from the arguments. standard in as a newline-delimited list instead of from the arguments.
+ +

View File

@ -15,6 +15,7 @@
#include "wt-status.h" #include "wt-status.h"
#include "quote.h" #include "quote.h"
#include "sparse-index.h" #include "sparse-index.h"
#include "worktree.h"
static const char *empty_base = ""; static const char *empty_base = "";
@ -359,26 +360,23 @@ enum sparse_checkout_mode {
static int set_config(enum sparse_checkout_mode mode) static int set_config(enum sparse_checkout_mode mode)
{ {
const char *config_path; /* Update to use worktree config, if not already. */
if (init_worktree_config(the_repository)) {
if (upgrade_repository_format(1) < 0) error(_("failed to initialize worktree config"));
die(_("unable to upgrade repository format to enable worktreeConfig"));
if (git_config_set_gently("extensions.worktreeConfig", "true")) {
error(_("failed to set extensions.worktreeConfig setting"));
return 1; return 1;
} }
config_path = git_path("config.worktree"); if (repo_config_set_worktree_gently(the_repository,
git_config_set_in_file_gently(config_path,
"core.sparseCheckout", "core.sparseCheckout",
mode ? "true" : NULL); mode ? "true" : "false") ||
repo_config_set_worktree_gently(the_repository,
git_config_set_in_file_gently(config_path,
"core.sparseCheckoutCone", "core.sparseCheckoutCone",
mode == MODE_CONE_PATTERNS ? "true" : NULL); mode == MODE_CONE_PATTERNS ?
"true" : "false"))
return 1;
if (mode == MODE_NO_PATTERNS) if (mode == MODE_NO_PATTERNS)
set_sparse_index_config(the_repository, 0); return set_sparse_index_config(the_repository, 0);
return 0; return 0;
} }

View File

@ -99,13 +99,9 @@ static int convert_to_sparse_rec(struct index_state *istate,
int set_sparse_index_config(struct repository *repo, int enable) int set_sparse_index_config(struct repository *repo, int enable)
{ {
int res; int res = repo_config_set_worktree_gently(repo,
char *config_path = repo_git_path(repo, "config.worktree");
res = git_config_set_in_file_gently(config_path,
"index.sparse", "index.sparse",
enable ? "true" : NULL); enable ? "true" : "false");
free(config_path);
prepare_repo_settings(repo); prepare_repo_settings(repo);
repo->settings.sparse_index = enable; repo->settings.sparse_index = enable;
return res; return res;

View File

@ -117,7 +117,7 @@ test_expect_success 'switching to cone mode with non-cone mode patterns' '
cd bad-patterns && cd bad-patterns &&
git sparse-checkout init && git sparse-checkout init &&
git sparse-checkout add dir && git sparse-checkout add dir &&
git config core.sparseCheckoutCone true && git config --worktree core.sparseCheckoutCone true &&
test_must_fail git sparse-checkout add dir 2>err && test_must_fail git sparse-checkout add dir 2>err &&
grep "existing sparse-checkout patterns do not use cone mode" err grep "existing sparse-checkout patterns do not use cone mode" err
) )
@ -256,7 +256,7 @@ test_expect_success 'sparse-index enabled and disabled' '
test_cmp expect actual && test_cmp expect actual &&
git -C repo config --list >config && git -C repo config --list >config &&
! grep index.sparse config test_cmp_config -C repo false index.sparse
) )
' '