Show 93 quoted lines
> From: Derrick Stolee <dstolee@microsoft.com>
>
> When adding a new worktree, it is reasonable to expect that we want to
> use the current set of sparse-checkout settings for that new worktree.
> This is particularly important for repositories where the worktree would
> become too large to be useful. This is even more important when using
> partial clone as well, since we want to avoid downloading the missing
> blobs for files that should not be written to the new worktree.
>
> The only way to create such a worktree without this intermediate step of
> expanding the full worktree is to copy the sparse-checkout patterns and
> config settings during 'git worktree add'. Each worktree has its own
> sparse-checkout patterns, and the default behavior when the
> sparse-checkout file is missing is to include all paths at HEAD. Thus,
> we need to have patterns from somewhere, they might as well be the
> current worktree's patterns. These are then modified independently in
> the future.
>
> In addition to the sparse-checkout file, copy the worktree config file
> if worktree config is enabled and the file exists. This will copy over
> any important settings to ensure the new worktree behaves the same as
> the current one. The only exception we must continue to make is that
> core.bare and core.worktree should become unset in the worktree's config
> file.
>
> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
> ---
> builtin/worktree.c | 60 ++++++++++++++++++++++++++++++
> t/t1091-sparse-checkout-builtin.sh | 31 +++++++++++----
> t/t2400-worktree-add.sh | 46 ++++++++++++++++++++++-
> 3 files changed, 127 insertions(+), 10 deletions(-)
>
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index 2838254f7f2..dc9cd6decc8 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -335,6 +335,66 @@ static int add_worktree(const char *path, const char *refname,
> strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
> write_file(sb.buf, "../..");
>
> + /*
> + * If the current worktree has sparse-checkout enabled, then copy
> + * the sparse-checkout patterns from the current worktree.
> + */
> + if (core_apply_sparse_checkout) {
> + char *from_file = git_pathdup("info/sparse-checkout");
> + char *to_file = xstrfmt("%s/worktrees/%s/info/sparse-checkout",
> + realpath.buf, name);
> +
> + if (file_exists(from_file)) {
> + if (safe_create_leading_directories(to_file) ||
> + copy_file(to_file, from_file, 0666))
> + error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"),
> + from_file, to_file);
> + }
> +
> + free(from_file);
> + free(to_file);
> + }
> +
> + /*
> + * If we are using worktree config, then copy all current config
> + * 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) {
> + char *from_file = git_pathdup("config.worktree");
> + char *to_file = xstrfmt("%s/worktrees/%s/config.worktree",
> + realpath.buf, name);
> +
> + if (file_exists(from_file)) {
> + struct config_set cs = { { 0 }};
> + const char *str_value;
> + int bool_value;
> +
> + if (safe_create_leading_directories(to_file) ||
> + copy_file(to_file, from_file, 0666))
> + die(_("failed to copy worktree config from '%s' to '%s'"),
> + from_file, to_file);
> +
> + git_configset_init(&cs);
> + git_configset_add_file(&cs, from_file);
> +
> + if (!git_configset_get_bool(&cs, "core.bare", &bool_value) &&
> + bool_value &&
> + git_config_set_multivar_in_file_gently(
> + to_file, "core.bare", NULL, "true", 0))
> + error(_("failed to unset 'core.bare' in '%s'"), to_file);
> + if (!git_configset_get_value(&cs, "core.worktree", &str_value) &&
> + git_config_set_in_file_gently(to_file,
> + "core.worktree", NULL))
> + error(_("failed to unset 'core.worktree' in '%s'"), to_file);
> +