All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jacob Abel <jacobabel@nullpo.dev>
To: git@vger.kernel.org
Cc: "Jacob Abel" <jacobabel@nullpo.dev>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Eric Sunshine" <sunshine@sunshineco.com>,
	"Junio C Hamano" <gitster@pobox.com>,
	"Phillip Wood" <phillip.wood123@gmail.com>,
	"Rubén Justo" <rjusto@gmail.com>, "Taylor Blau" <me@ttaylorr.com>,
	rsbecker@nexbridge.com
Subject: [PATCH v9 6/8] worktree add: introduce "try --orphan" hint
Date: Mon, 17 Apr 2023 09:34:19 +0000	[thread overview]
Message-ID: <20230417093255.31079-7-jacobabel@nullpo.dev> (raw)
In-Reply-To: <20230417093255.31079-1-jacobabel@nullpo.dev>

Add a new advice/hint in `git worktree add` for when the user
tries to create a new worktree from a reference that doesn't exist.

Current Behavior:

% git init foo
Initialized empty Git repository in /path/to/foo/
% touch file
% git -C foo commit -q -a -m "test commit"
% git -C foo switch --orphan norefbranch
% git -C foo worktree add newbranch/
Preparing worktree (new branch 'newbranch')
fatal: invalid reference: HEAD
%

New Behavior:

% git init --bare foo
Initialized empty Git repository in /path/to/foo/
% touch file
% git -C foo commit -q -a -m "test commit"
% git -C foo switch --orphan norefbranch
% git -C foo worktree add newbranch/
Preparing worktree (new branch 'newbranch')
hint: If you meant to create a worktree containing a new orphan branch
hint: (branch with no commits) for this repository, you can do so
hint: using the --orphan option:
hint:
hint:   git worktree add --orphan newbranch/
hint:
hint: Disable this message with "git config advice.worktreeAddOrphan false"
fatal: invalid reference: HEAD
% git -C foo worktree add -b newbranch2 new_wt/
Preparing worktree (new branch 'newbranch')
hint: If you meant to create a worktree containing a new orphan branch
hint: (branch with no commits) for this repository, you can do so
hint: using the --orphan option:
hint:
hint:   git worktree add --orphan -b newbranch2 new_wt/
hint:
hint: Disable this message with "git config advice.worktreeAddOrphan false"
fatal: invalid reference: HEAD
%

Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
---
 Documentation/config/advice.txt |  4 ++++
 advice.c                        |  1 +
 advice.h                        |  1 +
 builtin/worktree.c              | 25 +++++++++++++++++++++
 t/t2400-worktree-add.sh         | 39 +++++++++++++++++++++++++++++++++
 5 files changed, 70 insertions(+)

diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index c96b5b2e5d..c548a91e67 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -138,4 +138,8 @@ advice.*::
 		checkout.
 	diverging::
 		Advice shown when a fast-forward is not possible.
+	worktreeAddOrphan::
+		Advice shown when a user tries to create a worktree from an
+		invalid reference, to instruct how to create a new orphan
+		branch instead.
 --
diff --git a/advice.c b/advice.c
index d6232439c3..e5a9bb9b44 100644
--- a/advice.c
+++ b/advice.c
@@ -78,6 +78,7 @@ static struct {
 	[ADVICE_SUBMODULES_NOT_UPDATED] 		= { "submodulesNotUpdated", 1 },
 	[ADVICE_UPDATE_SPARSE_PATH]			= { "updateSparsePath", 1 },
 	[ADVICE_WAITING_FOR_EDITOR]			= { "waitingForEditor", 1 },
+	[ADVICE_WORKTREE_ADD_ORPHAN]			= { "worktreeAddOrphan", 1 },
 };

 static const char turn_off_instructions[] =
diff --git a/advice.h b/advice.h
index 0f584163f5..2affbe1426 100644
--- a/advice.h
+++ b/advice.h
@@ -49,6 +49,7 @@ struct string_list;
 	ADVICE_UPDATE_SPARSE_PATH,
 	ADVICE_WAITING_FOR_EDITOR,
 	ADVICE_SKIPPED_CHERRY_PICKS,
+	ADVICE_WORKTREE_ADD_ORPHAN,
 };

 int git_default_advice_config(const char *var, const char *value);
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 48de7fc3b0..12348d3d16 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -39,6 +39,20 @@
 #define BUILTIN_WORKTREE_UNLOCK_USAGE \
 	N_("git worktree unlock <worktree>")

+#define WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT \
+	_("If you meant to create a worktree containing a new orphan branch\n" \
+	"(branch with no commits) for this repository, you can do so\n" \
+	"using the --orphan flag:\n" \
+	"\n" \
+	"	git worktree add --orphan -b %s %s\n")
+
+#define WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT \
+	_("If you meant to create a worktree containing a new orphan branch\n" \
+	"(branch with no commits) for this repository, you can do so\n" \
+	"using the --orphan flag:\n" \
+	"\n" \
+	"	git worktree add --orphan %s\n")
+
 static const char * const git_worktree_usage[] = {
 	BUILTIN_WORKTREE_ADD_USAGE,
 	BUILTIN_WORKTREE_LIST_USAGE,
@@ -634,6 +648,7 @@ static int add(int ac, const char **av, const char *prefix)
 	const char *opt_track = NULL;
 	const char *lock_reason = NULL;
 	int keep_locked = 0;
+	int used_new_branch_options;
 	struct option options[] = {
 		OPT__FORCE(&opts.force,
 			   N_("checkout <branch> even if already checked out in other worktree"),
@@ -686,6 +701,7 @@ static int add(int ac, const char **av, const char *prefix)

 	path = prefix_filename(prefix, av[0]);
 	branch = ac < 2 ? "HEAD" : av[1];
+	used_new_branch_options = new_branch || new_branch_force;

 	if (!strcmp(branch, "-"))
 		branch = "@{-1}";
@@ -728,6 +744,15 @@ static int add(int ac, const char **av, const char *prefix)
 	}

 	if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
+		int attempt_hint = !opts.quiet && (ac < 2);
+		if (attempt_hint && used_new_branch_options) {
+			advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
+				WORKTREE_ADD_ORPHAN_WITH_DASH_B_HINT_TEXT,
+				new_branch, path);
+		} else if (attempt_hint) {
+			advise_if_enabled(ADVICE_WORKTREE_ADD_ORPHAN,
+				WORKTREE_ADD_ORPHAN_NO_DASH_B_HINT_TEXT, path);
+		}
 		die(_("invalid reference: %s"), branch);
 	}

diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index 2ea4342867..7ea56ef7c1 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -405,6 +405,45 @@ test_expect_success '"add" worktree with orphan branch, lock, and reason' '
 	test_cmp expect .git/worktrees/orphan-with-lock-reason/locked
 '

+# Note: Quoted arguments containing spaces are not supported.
+test_wt_add_orphan_hint () {
+	local context="$1" &&
+	local use_branch=$2 &&
+	shift 2 &&
+	local opts="$*" &&
+	test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" '
+		test_when_finished "rm -rf repo" &&
+		git init repo &&
+		(cd repo && test_commit commit) &&
+		git -C repo switch --orphan noref &&
+		test_when_finished cat actual >&2 &&
+		test_must_fail git -C repo worktree add $opts foobar/ 2>actual &&
+		! grep "error: unknown switch" actual &&
+		grep "hint: If you meant to create a worktree containing a new orphan branch" actual &&
+		if [ $use_branch -eq 1 ]
+		then
+			grep -E "^hint:\s+git worktree add --orphan -b \S+ \S+\s*$" actual
+		else
+			grep -E "^hint:\s+git worktree add --orphan \S+\s*$" actual
+		fi
+
+	'
+}
+
+test_wt_add_orphan_hint 'no opts' 0
+test_wt_add_orphan_hint '-b' 1 -b foobar_branch
+test_wt_add_orphan_hint '-B' 1 -B foobar_branch
+
+test_expect_success "'worktree add' doesn't show orphan hint in bad/orphan HEAD w/ --quiet" '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(cd repo && test_commit commit) &&
+	test_when_finished cat actual >&2 &&
+	test_must_fail git -C repo worktree add --quiet foobar_branch foobar/ 2>actual &&
+	! grep "error: unknown switch" actual &&
+	! grep "hint: If you meant to create a worktree containing a new orphan branch" actual
+'
+
 test_expect_success 'local clone from linked checkout' '
 	git clone --local here here-clone &&
 	( cd here-clone && git fsck )
--
2.39.2



  parent reply	other threads:[~2023-04-17  9:37 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-17  9:33 [PATCH v9 0/8] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2023-04-17  9:33 ` [PATCH v9 1/8] worktree add: include -B in usage docs Jacob Abel
2023-04-17  9:33 ` [PATCH v9 2/8] t2400: print captured git output when finished Jacob Abel
2023-04-17 21:09   ` Junio C Hamano
2023-04-18  3:53     ` Jacob Abel
2023-04-18 16:34       ` Junio C Hamano
2023-04-19 13:23         ` Jacob Abel
2023-04-19 13:36         ` Jacob Abel
2023-04-19 15:41           ` Junio C Hamano
2023-04-19 16:50             ` Jacob Abel
2023-04-17  9:33 ` [PATCH v9 3/8] t2400: refactor "worktree add" opt exclusion tests Jacob Abel
2023-04-17 21:30   ` Junio C Hamano
2023-04-20  2:46     ` Jacob Abel
2023-04-17  9:34 ` [PATCH v9 4/8] t2400: add tests to verify --quiet Jacob Abel
2023-04-17 21:33   ` Junio C Hamano
2023-04-20  2:48     ` Jacob Abel
2023-04-17  9:34 ` [PATCH v9 5/8] worktree add: add --orphan flag Jacob Abel
2023-04-17  9:34 ` Jacob Abel [this message]
2023-04-17  9:34 ` [PATCH v9 7/8] worktree add: extend DWIM to infer --orphan Jacob Abel
2023-04-17  9:34 ` [PATCH v9 8/8] worktree add: emit warn when there is a bad HEAD Jacob Abel
2023-04-20  3:05 ` [PATCH v9 0/8] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2023-05-01 21:51   ` Junio C Hamano
2023-05-02  5:48     ` Jacob Abel
2023-05-17 21:47 ` [RESEND PATCH v10 " Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 1/8] worktree add: include -B in usage docs Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 2/8] t2400: cleanup created worktree in test Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 3/8] t2400: refactor "worktree add" opt exclusion tests Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 4/8] t2400: add tests to verify --quiet Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 5/8] worktree add: add --orphan flag Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 6/8] worktree add: introduce "try --orphan" hint Jacob Abel
2023-05-17 21:48   ` [RESEND PATCH v10 7/8] worktree add: extend DWIM to infer --orphan Jacob Abel
2023-08-09  6:47     ` RESEND [PATCH " Teng Long
2023-08-11 17:43       ` Jacob Abel
2023-05-17 21:49   ` [RESEND PATCH v10 8/8] worktree add: emit warn when there is a bad HEAD Jacob Abel

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=20230417093255.31079-7-jacobabel@nullpo.dev \
    --to=jacobabel@nullpo.dev \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=me@ttaylorr.com \
    --cc=phillip.wood123@gmail.com \
    --cc=rjusto@gmail.com \
    --cc=rsbecker@nexbridge.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 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.