All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ghanshyam Thakkar <shyamthakkar001@gmail.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, ps@pks.im,
	Ghanshyam Thakkar <shyamthakkar001@gmail.com>
Subject: [PATCH v3 2/2] add-patch: classify '@' as a synonym for 'HEAD'
Date: Sat,  3 Feb 2024 16:55:50 +0530	[thread overview]
Message-ID: <20240203112619.979239-6-shyamthakkar001@gmail.com> (raw)
In-Reply-To: <20240202150434.11256-1-shyamthakkar001@gmail.com>

Currently, (checkout, reset, restore) commands correctly take '@' as a
synonym for 'HEAD'. However, in patch mode (-p/--patch), for both '@' and
'HEAD', different prompts/messages are given by the commands mentioned
above. This is due to the literal and only string comparison with the word
'HEAD' in run_add_p(). Synonymity between '@' and 'HEAD' is obviously
desired, especially since '@' already resolves to 'HEAD'.

Therefore, make a new function user_meant_head() which takes the
revision string and compares it to 'HEAD' as well as '@'. However, in
builtin/checkout.c, there is a logic to convert all command line input
rev to the raw object name for underlying machinery (e.g., diff-index)
that does not recognize the <a>...<b> notation, but we'd need to leave
'HEAD' intact.  Now we need to teach that '@' is a synonym to 'HEAD'
 to that code and leave '@' intact, too.

There is one unintended side-effect/behavior change of this, even if
there exists a branch named '@', when providing '@' as a rev-source to
(checkout, reset, restore) commands in patch mode, it will consider it
as HEAD. This is due to the behavior of diff-index. However, naming a
branch '@' is an obvious foot-gun and there are many existing commands
which take '@' for 'HEAD' even if 'refs/heads/@' exists (e.g., 'git log
@', 'git push origin @' etc.). Therefore, this should be fine.

Also, add tests to check the above mentioned synonymity between 'HEAD'
and '@'.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com>
---
 add-patch.c               | 11 +++++++---
 builtin/checkout.c        | 11 +++++-----
 t/t2016-checkout-patch.sh | 46 ++++++++++++++++++++++-----------------
 t/t2071-restore-patch.sh  | 18 +++++++++------
 t/t7105-reset-patch.sh    | 10 +++++++++
 5 files changed, 61 insertions(+), 35 deletions(-)

diff --git a/add-patch.c b/add-patch.c
index 68f525b35c..7d565dcb33 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -378,6 +378,11 @@ static int parse_hunk_header(struct add_p_state *s, struct hunk *hunk)
 	return 0;
 }
 
+static inline int user_meant_head(const char *rev)
+{
+	return !strcmp(rev, "HEAD") || !strcmp(rev, "@");
+}
+
 static int is_octal(const char *p, size_t len)
 {
 	if (!len)
@@ -1729,21 +1734,21 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
 	if (mode == ADD_P_STASH)
 		s.mode = &patch_mode_stash;
 	else if (mode == ADD_P_RESET) {
-		if (!revision || !strcmp(revision, "HEAD"))
+		if (!revision || user_meant_head(revision))
 			s.mode = &patch_mode_reset_head;
 		else
 			s.mode = &patch_mode_reset_nothead;
 	} else if (mode == ADD_P_CHECKOUT) {
 		if (!revision)
 			s.mode = &patch_mode_checkout_index;
-		else if (!strcmp(revision, "HEAD"))
+		else if (user_meant_head(revision))
 			s.mode = &patch_mode_checkout_head;
 		else
 			s.mode = &patch_mode_checkout_nothead;
 	} else if (mode == ADD_P_WORKTREE) {
 		if (!revision)
 			s.mode = &patch_mode_checkout_index;
-		else if (!strcmp(revision, "HEAD"))
+		else if (user_meant_head(revision))
 			s.mode = &patch_mode_worktree_head;
 		else
 			s.mode = &patch_mode_worktree_nothead;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index a6e30931b5..79e208ee6d 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -539,12 +539,13 @@ static int checkout_paths(const struct checkout_opts *opts,
 		 * recognized by diff-index), we will always replace the name
 		 * with the hex of the commit (whether it's in `...` form or
 		 * not) for the run_add_interactive() machinery to work
-		 * properly. However, there is special logic for the HEAD case
-		 * so we mustn't replace that.  Also, when we were given a
-		 * tree-object, new_branch_info->commit would be NULL, but we
-		 * do not have to do any replacement, either.
+		 * properly. However, there is special logic for the 'HEAD' and
+		 * '@' case so we mustn't replace that.  Also, when we were
+		 * given a tree-object, new_branch_info->commit would be NULL,
+		 * but we do not have to do any replacement, either.
 		 */
-		if (rev && new_branch_info->commit && strcmp(rev, "HEAD"))
+		if (rev && new_branch_info->commit && strcmp(rev, "HEAD") &&
+		    strcmp(rev, "@"))
 			rev = oid_to_hex_r(rev_oid, &new_branch_info->commit->object.oid);
 
 		if (opts->checkout_index && opts->checkout_worktree)
diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
index 747eb5563e..c4f9bf09aa 100755
--- a/t/t2016-checkout-patch.sh
+++ b/t/t2016-checkout-patch.sh
@@ -38,26 +38,32 @@ test_expect_success 'git checkout -p with staged changes' '
 	verify_state dir/foo index index
 '
 
-test_expect_success 'git checkout -p HEAD with NO staged changes: abort' '
-	set_and_save_state dir/foo work head &&
-	test_write_lines n y n | git checkout -p HEAD &&
-	verify_saved_state bar &&
-	verify_saved_state dir/foo
-'
-
-test_expect_success 'git checkout -p HEAD with NO staged changes: apply' '
-	test_write_lines n y y | git checkout -p HEAD &&
-	verify_saved_state bar &&
-	verify_state dir/foo head head
-'
-
-test_expect_success 'git checkout -p HEAD with change already staged' '
-	set_state dir/foo index index &&
-	# the third n is to get out in case it mistakenly does not apply
-	test_write_lines n y n | git checkout -p HEAD &&
-	verify_saved_state bar &&
-	verify_state dir/foo head head
-'
+for opt in "HEAD" "@"
+do
+	test_expect_success "git checkout -p $opt with NO staged changes: abort" '
+		set_and_save_state dir/foo work head &&
+		test_write_lines n y n | git checkout -p $opt >output &&
+		verify_saved_state bar &&
+		verify_saved_state dir/foo &&
+		test_grep "Discard" output
+	'
+
+	test_expect_success "git checkout -p $opt with NO staged changes: apply" '
+		test_write_lines n y y | git checkout -p $opt >output &&
+		verify_saved_state bar &&
+		verify_state dir/foo head head &&
+		test_grep "Discard" output
+	'
+
+	test_expect_success "git checkout -p $opt with change already staged" '
+		set_state dir/foo index index &&
+		# the third n is to get out in case it mistakenly does not apply
+		test_write_lines n y n | git checkout -p $opt >output &&
+		verify_saved_state bar &&
+		verify_state dir/foo head head &&
+		test_grep "Discard" output
+	'
+done
 
 test_expect_success 'git checkout -p HEAD^...' '
 	# the third n is to get out in case it mistakenly does not apply
diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh
index b5c5c0ff7e..3dc9184b4a 100755
--- a/t/t2071-restore-patch.sh
+++ b/t/t2071-restore-patch.sh
@@ -44,13 +44,17 @@ test_expect_success PERL 'git restore -p with staged changes' '
 	verify_state dir/foo index index
 '
 
-test_expect_success PERL 'git restore -p --source=HEAD' '
-	set_state dir/foo work index &&
-	# the third n is to get out in case it mistakenly does not apply
-	test_write_lines n y n | git restore -p --source=HEAD &&
-	verify_saved_state bar &&
-	verify_state dir/foo head index
-'
+for opt in "HEAD" "@"
+do
+	test_expect_success PERL "git restore -p --source=$opt" '
+		set_state dir/foo work index &&
+		# the third n is to get out in case it mistakenly does not apply
+		test_write_lines n y n | git restore -p --source=$opt >output &&
+		verify_saved_state bar &&
+		verify_state dir/foo head index &&
+		test_grep "Discard" output
+	'
+done
 
 test_expect_success PERL 'git restore -p --source=HEAD^' '
 	set_state dir/foo work index &&
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index 05079c7246..ec7f16dfb6 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -33,6 +33,16 @@ test_expect_success PERL 'git reset -p' '
 	test_grep "Unstage" output
 '
 
+for opt in "HEAD" "@"
+do
+	test_expect_success PERL "git reset -p $opt" '
+		test_write_lines n y | git reset -p $opt >output &&
+		verify_state dir/foo work head &&
+		verify_saved_state bar &&
+		test_grep "Unstage" output
+	'
+done
+
 test_expect_success PERL 'git reset -p HEAD^' '
 	test_write_lines n y | git reset -p HEAD^ >output &&
 	verify_state dir/foo work parent &&
-- 
2.43.0


  parent reply	other threads:[~2024-02-03 12:08 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-28 18:11 [GSOC][RFC PATCH 0/2] add-patch: compare object id Ghanshyam Thakkar
2024-01-28 18:11 ` [RFC PATCH 1/2] add-patch: compare object id instead of literal string Ghanshyam Thakkar
2024-01-29 11:48   ` Patrick Steinhardt
2024-01-30  6:39     ` Ghanshyam Thakkar
2024-01-30 16:42       ` Junio C Hamano
2024-01-29 18:27   ` Junio C Hamano
2024-01-29 18:58     ` Junio C Hamano
2024-01-30  5:35     ` Ghanshyam Thakkar
2024-01-28 18:11 ` [RFC PATCH 2/2] checkout: remove HEAD special case Ghanshyam Thakkar
2024-01-29 11:48   ` Patrick Steinhardt
2024-02-02 15:03 ` [PATCH v2 0/2] add-patch: Support '@' as a synonym for 'HEAD' Ghanshyam Thakkar
2024-02-02 15:03   ` [PATCH v2 1/2] add-patch: remove non-relevant NEEDSWORK comment Ghanshyam Thakkar
2024-02-02 15:03   ` [PATCH v2 2/2] add-patch: classify '@' as a synonym for 'HEAD' Ghanshyam Thakkar
2024-02-02 17:08     ` Junio C Hamano
2024-02-02 17:43       ` Junio C Hamano
2024-02-02 17:53         ` Ghanshyam Thakkar
2024-02-02 17:51       ` Ghanshyam Thakkar
2024-02-02 17:31   ` [PATCH v2 0/2] add-patch: Support " Ghanshyam Thakkar
2024-02-03 11:25   ` [PATCH v3 0/2] add-patch: " Ghanshyam Thakkar
2024-02-06 22:50     ` [PATCH v4 0/3] '@' as a synonym for 'HEAD' in patch mode Ghanshyam Thakkar
2024-02-11 20:20       ` [PATCH v5 0/2] add-patch: classify '@' as a synonym for 'HEAD' Ghanshyam Thakkar
2024-02-13  0:05         ` [PATCH v6 " Ghanshyam Thakkar
2024-02-14 11:06           ` Phillip Wood
2024-02-13  0:05         ` [PATCH v6 1/2] " Ghanshyam Thakkar
2024-02-13  0:05         ` [PATCH v6 2/2] add -p tests: remove PERL prerequisites Ghanshyam Thakkar
2024-02-11 20:20       ` [PATCH v5 1/2] add-patch: classify '@' as a synonym for 'HEAD' Ghanshyam Thakkar
2024-02-12 21:45         ` Junio C Hamano
2024-02-11 20:20       ` [PATCH v5 2/2] add -p tests: remove PERL prerequisites Ghanshyam Thakkar
2024-02-06 22:50     ` [PATCH v4 1/3] add-patch: remove unnecessary NEEDSWORK comment Ghanshyam Thakkar
2024-02-07 10:51       ` Phillip Wood
2024-02-06 22:50     ` [PATCH v4 2/3] add-patch: classify '@' as a synonym for 'HEAD' Ghanshyam Thakkar
2024-02-07  1:05       ` Junio C Hamano
2024-02-07 10:38         ` Phillip Wood
2024-02-09 15:57         ` Ghanshyam Thakkar
2024-02-06 22:50     ` [PATCH v4 3/3] add -p tests: remove Perl prerequisite Ghanshyam Thakkar
2024-02-07 10:50       ` Phillip Wood
2024-02-07 13:51         ` Phillip Wood
2024-02-07 16:02           ` Junio C Hamano
2024-02-07 16:58           ` Eric Sunshine
2024-02-03 11:25   ` [PATCH v3 1/2] add-patch: remove unnecessary NEEDSWORK comment Ghanshyam Thakkar
2024-02-03 11:25   ` Ghanshyam Thakkar [this message]
2024-02-03 22:33     ` [PATCH v3 2/2] add-patch: classify '@' as a synonym for 'HEAD' Junio C Hamano
2024-02-05 15:14       ` Ghanshyam Thakkar
2024-02-05 16:37     ` Phillip Wood
2024-02-05 20:38       ` Ghanshyam Thakkar
2024-02-05 23:07       ` Junio C Hamano

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=20240203112619.979239-6-shyamthakkar001@gmail.com \
    --to=shyamthakkar001@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=ps@pks.im \
    /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.