All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Carlo Marcelo Arenas Belón" <carenas@gmail.com>
To: git@vger.kernel.org
Cc: vustthat@gmail.com, sunshine@sunshineco.com, pclouds@gmail.com,
	"Carlo Marcelo Arenas Belón" <carenas@gmail.com>
Subject: [PATCH] builtin/checkout: check the branch used in -B with worktrees
Date: Mon, 16 Jan 2023 09:28:24 -0800	[thread overview]
Message-ID: <20230116172824.93218-1-carenas@gmail.com> (raw)

When multiple worktrees are being used, checkout/switch check
that the target branch is not already checked out with code that
evolved from 8d9fdd7087 (worktree.c: check whether branch is rebased
in another worktree, 2016-04-22), but that logic wasn't valid for
-B/-C

Avoid reusing the same `branch_info` structure for the checks and
assumming that it will be rejected later if is a new branch that
already exists as that doesn't apply to -B/-C.

Reported-by: Jinwook Jeong <vustthat@gmail.com>
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
---
 builtin/checkout.c      | 22 ++++++++++++++++------
 t/t2400-worktree-add.sh | 14 ++++++++++++++
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3fa29a08ee..94dcd617ef 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1474,7 +1474,8 @@ static void die_if_some_operation_in_progress(void)
 }
 
 static int checkout_branch(struct checkout_opts *opts,
-			   struct branch_info *new_branch_info)
+			   struct branch_info *new_branch_info,
+			   struct branch_info *check_branch_info)
 {
 	if (opts->pathspec.nr)
 		die(_("paths cannot be used with switching branches"));
@@ -1533,13 +1534,12 @@ static int checkout_branch(struct checkout_opts *opts,
 	if (!opts->can_switch_when_in_progress)
 		die_if_some_operation_in_progress();
 
-	if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
-	    !opts->ignore_other_worktrees) {
+	if (check_branch_info->path && !opts->force_detach && !opts->ignore_other_worktrees) {
 		int flag;
 		char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
 		if (head_ref &&
-		    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new_branch_info->path)))
-			die_if_checked_out(new_branch_info->path, 1);
+		    (!(flag & REF_ISSYMREF) || strcmp(head_ref, check_branch_info->path)))
+			die_if_checked_out(check_branch_info->path, 1);
 		free(head_ref);
 	}
 
@@ -1628,6 +1628,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			 struct branch_info *new_branch_info)
 {
 	int parseopt_flags = 0;
+	struct branch_info check_branch_info = { 0 };
 
 	opts->overwrite_ignore = 1;
 	opts->prefix = prefix;
@@ -1739,6 +1740,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			!opts->new_branch;
 		int n = parse_branchname_arg(argc, argv, dwim_ok,
 					     new_branch_info, opts, &rev);
+		check_branch_info = *new_branch_info;
 		argv += n;
 		argc -= n;
 	} else if (!opts->accept_ref && opts->from_treeish) {
@@ -1751,8 +1753,16 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 						      opts, &rev,
 						      opts->from_treeish);
 
+		check_branch_info = *new_branch_info;
 		if (!opts->source_tree)
 			die(_("reference is not a tree: %s"), opts->from_treeish);
+	} else if (opts->new_branch) {
+		struct object_id rev;
+
+		if (!get_oid_mb(opts->new_branch, &rev))
+			setup_new_branch_info_and_source_tree(&check_branch_info,
+							opts, &rev,
+							opts->new_branch);
 	}
 
 	if (argc) {
@@ -1819,7 +1829,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	if (opts->patch_mode || opts->pathspec.nr)
 		return checkout_paths(opts, new_branch_info);
 	else
-		return checkout_branch(opts, new_branch_info);
+		return checkout_branch(opts, new_branch_info, &check_branch_info);
 }
 
 int cmd_checkout(int argc, const char **argv, const char *prefix)
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index d587e0b20d..283ba7607e 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -125,6 +125,13 @@ test_expect_success 'die the same branch is already checked out' '
 	)
 '
 
+test_expect_success 'die the same branch is already checked out (checkout -B)' '
+	(
+		cd here &&
+		test_must_fail git checkout -B newmain
+	)
+'
+
 test_expect_success SYMLINKS 'die the same branch is already checked out (symlink)' '
 	head=$(git -C there rev-parse --git-path HEAD) &&
 	ref=$(git -C there symbolic-ref HEAD) &&
@@ -147,6 +154,13 @@ test_expect_success 'not die on re-checking out current branch' '
 	)
 '
 
+test_expect_success 'not die on re-checking out current branch (checkout -B)' '
+	(
+		cd there &&
+		git checkout -B newmain
+	)
+'
+
 test_expect_success '"add" from a bare repo' '
 	(
 		git clone --bare . bare &&
-- 
2.39.0.1.g119e9c6876.dirty


             reply	other threads:[~2023-01-16 17:50 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-16 17:28 Carlo Marcelo Arenas Belón [this message]
2023-01-16 22:18 ` [PATCH] builtin/checkout: check the branch used in -B with worktrees Eric Sunshine
2023-01-17  0:53 ` Rubén Justo
2023-01-18  5:44   ` Carlo Arenas
2023-01-18  6:15 ` [PATCH v2] checkout/switch: disallow checking out same branch in multiple worktrees Carlo Marcelo Arenas Belón
2023-01-18  6:52   ` Junio C Hamano
2023-01-18  7:58     ` Carlo Arenas
2023-01-18 16:10       ` Junio C Hamano
2023-01-18 22:55   ` Junio C Hamano
2023-01-19  5:53   ` [PATCH v3] " Carlo Marcelo Arenas Belón
2023-01-19  7:23     ` Re* " Junio C Hamano
2023-01-19  7:41       ` Carlo Arenas
2023-01-19 14:21     ` Phillip Wood
2023-01-20  3:10     ` Junio C Hamano
2023-01-20  3:53       ` Carlo Arenas
2023-01-20  4:39         ` Carlo Arenas
2023-01-20 11:35     ` [PATCH v4] " Carlo Marcelo Arenas Belón
2023-01-20 15:08       ` Phillip Wood
2023-01-20 22:12         ` Carlo Arenas
2023-01-27 14:46           ` Phillip Wood
2023-05-14 20:21             ` Rubén Justo
2023-03-23  0:06         ` Junio C Hamano
2023-03-24  3:49           ` Carlo Arenas
2023-05-14 20:24       ` Rubén Justo

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=20230116172824.93218-1-carenas@gmail.com \
    --to=carenas@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=pclouds@gmail.com \
    --cc=sunshine@sunshineco.com \
    --cc=vustthat@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.