git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] am: let command-line options override saved options

From
Paul Tan <pyokagan@gmail.com>
Date
Jul 28, 2015, 16:43 UTC
Message-ID
<20150728164311.GA1948@yoshi.chippynet.com>
In-Reply-To
<xmqq8ua1k7fc.fsf@gitster.dls.corp.google.com>

When resuming, git-am ignores command-line options. For instance, when a patch fails to apply with "git am patch", subsequently running "git am --3way patch" would not cause git-am to fall back on attempting a threeway merge. This occurs because by default the --3way option is saved as "false", and the saved am options are loaded after the command-line options are parsed, thus overwriting the command-line options when resuming.

Fix this by moving the am_load() function call before parse_options(), so that command-line options will override the saved am options.

Reported-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Paul Tan <pyokagan@gmail.com>
---
 builtin/am.c                       |   9 ++-
 t/t4153-am-resume-override-opts.sh | 144 +++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 3 deletions(-)
 create mode 100755 t/t4153-am-resume-override-opts.sh
diff --git a/builtin/am.c b/builtin/am.c
index 1116304..8a0b0e4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -2131,6 +2131,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 	int keep_cr = -1;
 	int patch_format = PATCH_FORMAT_UNKNOWN;
 	enum resume_mode resume = RESUME_FALSE;
+	int in_progress;
 
 	const char * const usage[] = {
 		N_("git am [options] [(<mbox>|<Maildir>)...]"),
@@ -2226,6 +2227,10 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
 	am_state_init(&state, git_path("rebase-apply"));
 
+	in_progress = am_in_progress(&state);
+	if (in_progress)
+		am_load(&state);
+
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 
 	if (binary >= 0)
@@ -2238,7 +2243,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 	if (read_index_preload(&the_index, NULL) < 0)
 		die(_("failed to read the index"));
 
-	if (am_in_progress(&state)) {
+	if (in_progress) {
 		/*
 		 * Catch user error to feed us patches when there is a session
 		 * in progress:
@@ -2256,8 +2261,6 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
 		if (resume == RESUME_FALSE)
 			resume = RESUME_APPLY;
-
-		am_load(&state);
 	} else {
 		struct argv_array paths = ARGV_ARRAY_INIT;
 		int i;
diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh
new file mode 100755
index 0000000..c49457c
--- /dev/null
+++ b/t/t4153-am-resume-override-opts.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+test_description='git-am command-line options override saved options'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit initial file &&
+	test_commit first file &&
+
+	git checkout -b side initial &&
+	test_commit side-first file &&
+	test_commit side-second file &&
+
+	{
+		echo "Message-Id: <side-first@example.com>" &&
+		git format-patch --stdout -1 side-first | sed -e "1d"
+	} >side-first.patch &&
+	{
+		sed -ne "1,/^\$/p" side-first.patch &&
+		echo "-- >8 --" &&
+		sed -e "1,/^\$/d" side-first.patch
+	} >side-first.scissors &&
+
+	{
+		echo "Message-Id: <side-second@example.com>" &&
+		git format-patch --stdout -1 side-second | sed -e "1d"
+	} >side-second.patch &&
+	{
+		sed -ne "1,/^\$/p" side-second.patch &&
+		echo "-- >8 --" &&
+		sed -e "1,/^\$/d" side-second.patch
+	} >side-second.scissors
+'
+
+test_expect_success '--3way, --no-3way' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --3way side-first.patch side-second.patch &&
+	test -n "$(git ls-files -u)" &&
+	echo will-conflict >file &&
+	git add file &&
+	test_must_fail git am --no-3way --continue &&
+	test -z "$(git ls-files -u)"
+'
+
+test_expect_success '--no-quiet, --quiet' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --no-quiet side-first.patch side-second.patch &&
+	test_must_be_empty out &&
+	echo side-first >file &&
+	git add file &&
+	git am --quiet --continue >out &&
+	test_must_be_empty out
+'
+
+test_expect_success '--signoff, --no-signoff' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --signoff side-first.patch side-second.patch &&
+	echo side-first >file &&
+	git add file &&
+	git am --no-signoff --continue &&
+
+	# applied side-first will be signed off
+	echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
+	git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
+	test_cmp expected actual &&
+
+	# applied side-second will not be signed off
+	test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
+'
+
+test_expect_success '--keep, --no-keep' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --keep side-first.patch side-second.patch &&
+	echo side-first >file &&
+	git add file &&
+	git am --no-keep --continue &&
+
+	# applied side-first will keep the subject
+	git cat-file commit HEAD^ >actual &&
+	grep "^\[PATCH\] side-first" actual &&
+
+	# applied side-second will not have [PATCH]
+	git cat-file commit HEAD >actual &&
+	! grep "^\[PATCH\] side-second" actual
+'
+
+test_expect_success '--message-id, --no-message-id' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --message-id side-first.patch side-second.patch &&
+	echo side-first >file &&
+	git add file &&
+	git am --no-message-id --continue &&
+
+	# applied side-first will have Message-Id
+	test -n "$(git cat-file commit HEAD^ | grep Message-Id)" &&
+
+	# applied side-second will not have Message-Id
+	test -z "$(git cat-file commit HEAD | grep Message-Id)"
+'
+
+test_expect_success '--scissors, --no-scissors' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	test_must_fail git am --scissors side-first.scissors side-second.scissors &&
+	echo side-first >file &&
+	git add file &&
+	git am --no-scissors --continue &&
+
+	# applied side-first will not have scissors line
+	git cat-file commit HEAD^ >actual &&
+	! grep "^-- >8 --" actual &&
+
+	# applied side-second will have scissors line
+	git cat-file commit HEAD >actual &&
+	grep "^-- >8 --" actual
+'
+
+test_expect_success '--reject, --no-reject' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout first &&
+	rm -f file.rej &&
+	test_must_fail git am --reject side-first.patch side-second.patch &&
+	test_path_is_file file.rej &&
+	rm -f file.rej &&
+	echo will-conflict >file &&
+	git add file &&
+	test_must_fail git am --no-reject --continue &&
+	test_path_is_missing file.rej
+'
+
+test_done
-- 
2.5.0.77.gd180035
Previous: Junio C HamanoNext: Junio C Hamano
Message 8 of 26 in “"git am" and then "git am -3" regression?”
  1. Junio C HamanoJul 24, 2015
  2. Jeff KingJul 24, 2015
  3. Paul TanJul 26, 2015
  4. Jeff KingJul 26, 2015
  5. Matthieu MoyJul 27, 2015
  6. Jeff KingJul 27, 2015
  7. Junio C HamanoJul 27, 2015
  8. am: let command-line options override saved optionsPaul Tan, Jul 28, 2015
  9. Junio C HamanoJul 28, 2015
  10. Junio C HamanoJul 28, 2015
  11. Paul TanJul 31, 2015
  12. Junio C HamanoJul 31, 2015
  13. Paul TanAug 1, 2015
  14. 0/3 am: let command-line options override saved optionsPaul Tan, Aug 4, 2015
  15. Junio C HamanoAug 4, 2015
  16. 0/3 am: let command-line options override saved optionsPaul Tan, Aug 4, 2015
  17. 1/3 test_terminal: redirect child process' stdin to a ptyPaul Tan, Aug 4, 2015
  18. Eric SunshineAug 6, 2015
  19. Paul TanAug 12, 2015
  20. 2/3 am: let command-line options override saved optionsPaul Tan, Aug 4, 2015
  21. 3/3 am: let --signoff override --no-signoffPaul Tan, Aug 4, 2015
  22. Johannes SchindelinAug 7, 2015
  23. Paul TanAug 12, 2015
  24. Paul TanAug 12, 2015
  25. Junio C HamanoAug 5, 2015
  26. Paul TanAug 5, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.