git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: stolee@gmail.com, sunshine@sunshineco.com, allred.sean@gmail.com,
	gitster@pobox.com, "Elijah Newren" <newren@gmail.com>,
	"Bagas Sanjaya" <bagasdotme@gmail.com>,
	"Jean-Noël AVILA" <jn.avila@free.fr>,
	derrickstolee@github.com,
	"Derrick Stolee" <derrickstolee@github.com>,
	"Derrick Stolee" <dstolee@microsoft.com>
Subject: [PATCH v6 5/6] worktree: copy sparse-checkout patterns and config on add
Date: Mon, 07 Feb 2022 21:33:02 +0000	[thread overview]
Message-ID: <c51cb3714e7b1d2f8c9370fe87eca9984ff4859f.1644269584.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1101.v6.git.1644269583.gitgitgadget@gmail.com>

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                 | 63 ++++++++++++++++++++++++++++++
 t/t1091-sparse-checkout-builtin.sh | 31 +++++++++++----
 t/t2400-worktree-add.sh            | 58 ++++++++++++++++++++++++++-
 3 files changed, 142 insertions(+), 10 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 2838254f7f2..c6eb636329a 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -335,6 +335,69 @@ 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/info/sparse-checkout",
+					sb_repo.buf);
+
+		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/config.worktree",
+					sb_repo.buf);
+
+		if (file_exists(from_file)) {
+			struct config_set cs = { { 0 } };
+			const char *core_worktree;
+			int bare;
+
+			if (safe_create_leading_directories(to_file) ||
+			    copy_file(to_file, from_file, 0666)) {
+				error(_("failed to copy worktree config from '%s' to '%s'"),
+				      from_file, to_file);
+				goto worktree_copy_cleanup;
+			}
+
+			git_configset_init(&cs);
+			git_configset_add_file(&cs, from_file);
+
+			if (!git_configset_get_bool(&cs, "core.bare", &bare) &&
+			    bare &&
+			    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", &core_worktree) &&
+			    git_config_set_in_file_gently(to_file,
+							  "core.worktree", NULL))
+				error(_("failed to unset 'core.worktree' in '%s'"), to_file);
+
+			git_configset_clear(&cs);
+		}
+
+worktree_copy_cleanup:
+		free(from_file);
+		free(to_file);
+	}
+
 	strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
 	strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
 	cp.git_cmd = 1;
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index be6ea4ffe33..8a757b43e6c 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -146,9 +146,9 @@ test_expect_success 'interaction with clone --no-checkout (unborn index)' '
 '
 
 test_expect_success 'set enables config' '
-	git init empty-config &&
+	git init worktree-config &&
 	(
-		cd empty-config &&
+		cd worktree-config &&
 		test_commit test file &&
 		test_path_is_missing .git/config.worktree &&
 		git sparse-checkout set nothing &&
@@ -201,6 +201,21 @@ test_expect_success 'add to sparse-checkout' '
 	check_files repo "a folder1 folder2"
 '
 
+test_expect_success 'worktree: add copies sparse-checkout patterns' '
+	cat repo/.git/info/sparse-checkout >old &&
+	test_when_finished cp old repo/.git/info/sparse-checkout &&
+	test_when_finished git -C repo worktree remove ../worktree &&
+	git -C repo sparse-checkout set --no-cone "/*" &&
+	git -C repo worktree add --quiet ../worktree 2>err &&
+	test_must_be_empty err &&
+	new="$(git -C worktree rev-parse --git-path info/sparse-checkout)" &&
+	test_path_is_file "$new" &&
+	test_cmp repo/.git/info/sparse-checkout "$new" &&
+	git -C worktree sparse-checkout set --cone &&
+	test_cmp_config -C worktree true core.sparseCheckoutCone &&
+	test_must_fail git -C repo core.sparseCheckoutCone
+'
+
 test_expect_success 'cone mode: match patterns' '
 	git -C repo config --worktree core.sparseCheckoutCone true &&
 	rm -rf repo/a repo/folder1 repo/folder2 &&
@@ -520,13 +535,13 @@ test_expect_success 'interaction with submodules' '
 '
 
 test_expect_success 'different sparse-checkouts with worktrees' '
+	git -C repo sparse-checkout set --cone deep folder1 &&
 	git -C repo worktree add --detach ../worktree &&
-	check_files worktree "a deep folder1 folder2" &&
-	git -C worktree sparse-checkout init --cone &&
-	git -C repo sparse-checkout set folder1 &&
-	git -C worktree sparse-checkout set deep/deeper1 &&
-	check_files repo a folder1 &&
-	check_files worktree a deep
+	check_files worktree "a deep folder1" &&
+	git -C repo sparse-checkout set --cone folder1 &&
+	git -C worktree sparse-checkout set --cone deep/deeper1 &&
+	check_files repo "a folder1" &&
+	check_files worktree "a deep"
 '
 
 test_expect_success 'set using filename keeps file on-disk' '
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 37ad79470fb..43139af08fc 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -165,8 +165,62 @@ test_expect_success '"add" default branch of a bare repo' '
 	(
 		git clone --bare . bare2 &&
 		cd bare2 &&
-		git worktree add ../there3 main
-	)
+		git worktree add ../there3 main &&
+		cd ../there3 &&
+		# Simple check that a Git command does not
+		# immediately fail with the current setup
+		git status
+	) &&
+	cat >expect <<-EOF &&
+	init.t
+	EOF
+	ls there3 >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '"add" to bare repo with worktree config' '
+	(
+		git clone --bare . bare3 &&
+		cd bare3 &&
+		git config extensions.worktreeconfig true &&
+
+		# Add config values that are erroneous to have in
+		# a config.worktree file outside of the main
+		# working tree, to check that Git filters them out
+		# when copying config during "git worktree add".
+		git config --worktree core.bare true &&
+		git config --worktree core.worktree "$(pwd)" &&
+
+		# We want to check that bogus.key is copied
+		git config --worktree bogus.key value &&
+		git config --unset core.bare &&
+		git worktree add ../there4 main &&
+		cd ../there4 &&
+
+		# Simple check that a Git command does not
+		# immediately fail with the current setup
+		git status &&
+		git worktree add --detach ../there5 &&
+		cd ../there5 &&
+		git status
+	) &&
+
+	# the worktree has the arbitrary value copied.
+	test_cmp_config -C there4 value bogus.key &&
+	test_cmp_config -C there5 value bogus.key &&
+
+	# however, core.bare and core.worktree were removed.
+	test_must_fail git -C there4 config core.bare &&
+	test_must_fail git -C there4 config core.worktree &&
+
+	cat >expect <<-EOF &&
+	init.t
+	EOF
+
+	ls there4 >actual &&
+	test_cmp expect actual &&
+	ls there5 >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success 'checkout with grafts' '
-- 
gitgitgadget


  parent reply	other threads:[~2022-02-07 21:33 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-20 15:57 [PATCH 0/4] Sparse checkout: fix bug with worktree of bare repo Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 1/4] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 2/4] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-20 15:57 ` [PATCH 3/4] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-20 17:32   ` Derrick Stolee
2021-12-21  0:01     ` Eric Sunshine
2021-12-21  5:59       ` Eric Sunshine
2021-12-21 13:41       ` Derrick Stolee
2021-12-21  5:53   ` Eric Sunshine
2021-12-21 13:45     ` Derrick Stolee
2021-12-21 23:29       ` Eric Sunshine
2021-12-20 15:57 ` [PATCH 4/4] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-20 16:21 ` [PATCH 0/4] Sparse checkout: fix bug with worktree of bare repo Eric Sunshine
2021-12-20 17:34   ` Derrick Stolee
2021-12-21  6:10     ` Eric Sunshine
2021-12-21 19:14 ` [PATCH v2 0/5] " Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 1/5] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 2/5] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-21 19:14   ` [PATCH v2 3/5] worktree: add upgrade_to_worktree_config() Derrick Stolee via GitGitGadget
2021-12-22  0:45     ` Eric Sunshine
2021-12-28 15:03       ` Derrick Stolee
2021-12-28 16:58         ` Eric Sunshine
2021-12-28 17:03           ` Derrick Stolee
2021-12-22  5:38     ` Junio C Hamano
2021-12-28 15:13       ` Derrick Stolee
2021-12-21 19:14   ` [PATCH v2 4/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-22  1:11     ` Eric Sunshine
2021-12-21 19:14   ` [PATCH v2 5/5] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-22  5:48     ` Eric Sunshine
2021-12-22  6:05   ` [PATCH v2 0/5] Sparse checkout: fix bug with worktree of bare repo Eric Sunshine
2021-12-22 22:54   ` Elijah Newren
2021-12-27  7:15     ` Eric Sunshine
2021-12-27  7:34       ` Eric Sunshine
2021-12-27 20:16         ` Elijah Newren
2021-12-28  9:11           ` Eric Sunshine
2021-12-30  6:21           ` Eric Sunshine
2021-12-30 17:40             ` Elijah Newren
2021-12-27 19:35       ` Elijah Newren
2021-12-28  7:33         ` Eric Sunshine
2021-12-28 18:16           ` Elijah Newren
2021-12-30  6:40             ` Eric Sunshine
2021-12-30 18:38               ` Elijah Newren
2022-01-03  6:51                 ` Eric Sunshine
2021-12-28 21:32   ` [PATCH v3 0/6] " Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 1/6] setup: use a repository when upgrading format Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 2/6] config: make some helpers repo-aware Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 3/6] worktree: add 'init-worktree-config' subcommand Derrick Stolee via GitGitGadget
2021-12-29  6:48       ` Eric Sunshine
2021-12-30  8:41       ` Eric Sunshine
2021-12-30 17:29         ` Derrick Stolee
2022-01-03  6:38           ` Eric Sunshine
2021-12-28 21:32     ` [PATCH v3 4/6] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-28 21:32     ` [PATCH v3 5/6] sparse-checkout: use repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2021-12-30  9:01       ` Eric Sunshine
2021-12-28 21:32     ` [PATCH v3 6/6] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2021-12-29  6:37       ` Eric Sunshine
2021-12-29 17:31         ` Derrick Stolee
2021-12-29 19:51           ` Elijah Newren
2021-12-29 21:39             ` Derrick Stolee
2021-12-29 22:45               ` Elijah Newren
2021-12-30  8:16                 ` Eric Sunshine
2021-12-30  8:01             ` Eric Sunshine
2021-12-29  9:39     ` [PATCH v3 0/6] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2021-12-29 17:38       ` Derrick Stolee
2021-12-30  7:41         ` Eric Sunshine
2021-12-30  7:40       ` Eric Sunshine
2021-12-30 17:41         ` Derrick Stolee
2021-12-30 19:29           ` Elijah Newren
2022-01-03  7:11             ` Eric Sunshine
2021-12-30 18:46         ` Elijah Newren
2022-01-25 18:42     ` [PATCH v4 0/5] " Derrick Stolee via GitGitGadget
2022-01-25 18:42       ` [PATCH v4 1/5] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-01-26  6:59         ` Bagas Sanjaya
2022-01-27 14:15           ` Derrick Stolee
2022-01-27  6:43         ` Elijah Newren
2022-01-27 14:17           ` Derrick Stolee
2022-01-25 18:42       ` [PATCH v4 2/5] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-01-27  7:01         ` Elijah Newren
2022-01-25 18:42       ` [PATCH v4 3/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-01-25 18:42       ` [PATCH v4 4/5] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-01-27  7:15         ` Elijah Newren
2022-01-27 14:24           ` Derrick Stolee
2022-01-25 18:42       ` [PATCH v4 5/5] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2022-01-27  7:09         ` Elijah Newren
2022-01-27  7:20       ` [PATCH v4 0/5] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-01-27 14:29         ` Derrick Stolee
2022-01-31 15:00       ` [PATCH v5 " Derrick Stolee via GitGitGadget
2022-01-31 15:00         ` [PATCH v5 1/5] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-02-06  9:17           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 2/5] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-02-06  9:32           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 3/5] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-01-31 15:00         ` [PATCH v5 4/5] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-02-06 10:21           ` Eric Sunshine
2022-01-31 15:00         ` [PATCH v5 5/5] worktree: copy sparse-checkout patterns and config on add Derrick Stolee via GitGitGadget
2022-02-06 10:36           ` Jean-Noël AVILA
2022-02-07 14:10             ` Derrick Stolee
2022-02-09  7:53               ` Jean-Noël Avila
2022-02-09 14:45                 ` Derrick Stolee
2022-02-06 11:30           ` Eric Sunshine
2022-02-06 19:36             ` Eric Sunshine
2022-02-07 14:30             ` Derrick Stolee
2022-02-15 22:01               ` Eric Sunshine
2022-02-16 13:58                 ` Derrick Stolee
2022-01-31 16:17         ` [PATCH v5 0/5] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-02-07 21:32         ` [PATCH v6 0/6] " Derrick Stolee via GitGitGadget
2022-02-07 21:32           ` [PATCH v6 1/6] Documentation: add extensions.worktreeConfig details Derrick Stolee via GitGitGadget
2022-02-08 22:20             ` Junio C Hamano
2022-02-09  2:34               ` Derrick Stolee
2022-02-09 17:19                 ` Junio C Hamano
2022-02-09 17:26                   ` Derrick Stolee
2022-02-09 17:51                   ` Elijah Newren
2022-02-09 18:40                     ` Junio C Hamano
2022-02-15 20:37                 ` Eric Sunshine
2022-02-16  1:51                   ` Junio C Hamano
2022-02-09 18:04               ` Elijah Newren
2022-02-09 18:41                 ` Junio C Hamano
2022-02-07 21:32           ` [PATCH v6 2/6] worktree: create init_worktree_config() Derrick Stolee via GitGitGadget
2022-02-08 22:09             ` Junio C Hamano
2022-02-09  2:21               ` Derrick Stolee
2022-02-09 17:34                 ` Junio C Hamano
2022-02-09 16:43               ` Elijah Newren
2022-02-07 21:33           ` [PATCH v6 3/6] config: add repo_config_set_worktree_gently() Derrick Stolee via GitGitGadget
2022-02-08 22:18             ` Junio C Hamano
2022-02-09  2:27               ` Derrick Stolee
2022-02-09 17:49                 ` Junio C Hamano
2022-02-10 14:48                   ` Derrick Stolee
2022-02-10 16:45                     ` Junio C Hamano
2022-02-07 21:33           ` [PATCH v6 4/6] sparse-checkout: set worktree-config correctly Derrick Stolee via GitGitGadget
2022-02-07 21:33           ` Derrick Stolee via GitGitGadget [this message]
2022-02-15 22:23             ` [PATCH v6 5/6] worktree: copy sparse-checkout patterns and config on add Eric Sunshine
2022-02-07 21:33           ` [PATCH v6 6/6] config: make git_configset_get_string_tmp() private Derrick Stolee via GitGitGadget
2022-02-08  4:14           ` [PATCH v6 0/6] Sparse checkout: fix bug with worktree of bare repo Elijah Newren
2022-02-08  5:02             ` Eric Sunshine
2022-02-08  5:18               ` Elijah Newren
2022-02-08  5:42                 ` Eric Sunshine
2022-02-16  0:56                   ` Eric Sunshine
2022-02-08 14:33               ` Derrick Stolee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c51cb3714e7b1d2f8c9370fe87eca9984ff4859f.1644269584.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=allred.sean@gmail.com \
    --cc=bagasdotme@gmail.com \
    --cc=derrickstolee@github.com \
    --cc=dstolee@microsoft.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jn.avila@free.fr \
    --cc=newren@gmail.com \
    --cc=stolee@gmail.com \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).