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

[PATCH 3/4] rebase -m: fix serialization of strategy options

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Mar 15, 2023, 15:14 UTC
Message-ID
<9af68cb065871d9b89e99ef6b48870d322bb5faa.1678893298.git.phillip.wood@dunelm.org.uk>
In-Reply-To
<cover.1678893298.git.phillip.wood@dunelm.org.uk>
From: Phillip Wood <phillip.wood@dunelm.org.uk>

To store the strategy options rebase prepends " --" to each one and writes them to a file. To load them it reads the file and passes the contents to split_cmdline(). This roughly mimics the behavior of the scripted rebase but has a couple of limitations, (1) options containing whitespace are not properly preserved (this is true of the scripted rebase as well) and (2) options containing '"' or '\' are incorrectly parsed and may cause the parser to return an error.

Fix these limitations by quoting each option when they are stored so that they can be parsed correctly. Now that "--preserve-merges" no longer exist this change also stops prepending "--" to the options when they are stored as that was an artifact of the scripted rebase.

These changes are backwards compatible so the files written by an older version of git can be still be read. They are also forwards compatible, the file can still be parsed by recent versions of git as they treat the "--" prefix as optional.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 sequencer.c                    | 23 +++++++++++++++++++----
 t/t3418-rebase-continue.sh     | 34 ++++++++++++++++++++++------------
 t/t3436-rebase-more-options.sh | 24 ------------------------
 3 files changed, 41 insertions(+), 40 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 83ea1016ae..8890d1f7a1 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2930,7 +2930,7 @@ static void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
 	count = split_cmdline(strategy_opts_string,
 			      (const char ***)&opts->xopts);
 	if (count < 0)
-		die(_("could not split '%s': %s"), strategy_opts_string,
+		BUG("could not split '%s': %s", strategy_opts_string,
 			    split_cmdline_strerror(count));
 	opts->xopts_nr = count;
 	for (i = 0; i < opts->xopts_nr; i++) {
@@ -3054,12 +3054,27 @@ static int read_populate_opts(struct replay_opts *opts)
 
 static void write_strategy_opts(struct replay_opts *opts)
 {
-	int i;
 	struct strbuf buf = STRBUF_INIT;
 
-	for (i = 0; i < opts->xopts_nr; ++i)
-		strbuf_addf(&buf, " --%s", opts->xopts[i]);
+	/*
+	 * Quote strategy options so that they can be read correctly
+	 * by split_cmdline().
+	 */
+	for (size_t i = 0; i < opts->xopts_nr; i++) {
+		char *arg = opts->xopts[i];
 
+		if (i)
+			strbuf_addch(&buf, ' ');
+		strbuf_addch(&buf, '"');
+		for (size_t j = 0; arg[j]; j++) {
+			const char c = arg[j];
+
+			if (c == '"' || c =='\\')
+				strbuf_addch(&buf, '\\');
+			strbuf_addch(&buf, c);
+		}
+		strbuf_addch(&buf, '"');
+	}
 	write_file(rebase_path_strategy_opts(), "%s\n", buf.buf);
 	strbuf_release(&buf);
 }
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 130e2f9b55..42c3954125 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -62,29 +62,39 @@ test_expect_success 'rebase --continue remembers merge strategy and options' '
 	rm -fr .git/rebase-* &&
 	git reset --hard commit-new-file-F2-on-topic-branch &&
 	test_commit "commit-new-file-F3-on-topic-branch" F3 32 &&
-	test_when_finished "rm -fr test-bin funny.was.run" &&
+	test_when_finished "rm -fr test-bin" &&
 	mkdir test-bin &&
-	cat >test-bin/git-merge-funny <<-EOF &&
-	#!$SHELL_PATH
-	case "\$1" in --opt) ;; *) exit 2 ;; esac
-	shift &&
-	>funny.was.run &&
-	exec git merge-recursive "\$@"
+
+	write_script test-bin/git-merge-funny <<-\EOF &&
+	printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual
+	shift 3 &&
+	exec git merge-recursive "$@"
 	EOF
-	chmod +x test-bin/git-merge-funny &&
+
+	cat >expect <<-\EOF &&
+	[7]
+	[--option=arg with space]
+	[--op"tion\]
+	[--new
+	line ]
+	[--]
+	EOF
+
+	rm -f actual &&
 	(
 		PATH=./test-bin:$PATH &&
-		test_must_fail git rebase -s funny -Xopt main topic
+		test_must_fail git rebase -s funny -X"option=arg with space" \
+				-Xop\"tion\\ -X"new${LF}line " main topic
 	) &&
-	test -f funny.was.run &&
-	rm funny.was.run &&
+	test_cmp expect actual &&
+	rm actual &&
 	echo "Resolved" >F2 &&
 	git add F2 &&
 	(
 		PATH=./test-bin:$PATH &&
 		git rebase --continue
 	) &&
-	test -f funny.was.run
+	test_cmp expect actual
 '
 
 test_expect_success 'rebase -i --continue handles merge strategy and options' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 3adf42f47d..94671d3c46 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -40,30 +40,6 @@ test_expect_success 'setup' '
 	EOF
 '
 
-test_expect_success 'bad -X <strategy-option> arguments: unclosed quote' '
-	test_when_finished "test_might_fail git rebase --abort" &&
-	cat >expect <<-\EOF &&
-	fatal: could not split '\''--bad'\'': unclosed quote
-	EOF
-	GIT_SEQUENCE_EDITOR="echo break >" \
-		git rebase -i -X"bad argument\"" side main &&
-	test_expect_code 128 git rebase --continue >out 2>actual &&
-	test_must_be_empty out &&
-	test_cmp expect actual
-'
-
-test_expect_success 'bad -X <strategy-option> arguments: bad escape' '
-	test_when_finished "test_might_fail git rebase --abort" &&
-	cat >expect <<-\EOF &&
-	fatal: could not split '\''--bad'\'': cmdline ends with \
-	EOF
-	GIT_SEQUENCE_EDITOR="echo break >" \
-		git rebase -i -X"bad escape \\" side main &&
-	test_expect_code 128 git rebase --continue >out 2>actual &&
-	test_must_be_empty out &&
-	test_cmp expect actual
-'
-
 test_expect_success '--ignore-whitespace works with apply backend' '
 	test_must_fail git rebase --apply main side &&
 	git rebase --abort &&
-- 
2.39.2
Previous: Phillip WoodNext: Elijah Newren
Message 4 of 36 in “rebase: cleanup merge strategy option handling”
  1. 0/4 rebase: cleanup merge strategy option handlingPhillip Wood, Mar 15, 2023
  2. 1/4 rebase: stop reading and writing unnecessary strategy statePhillip Wood, Mar 15, 2023
  3. 2/4 rebase -m: cleanup --strategy-option handlingPhillip Wood, Mar 15, 2023
  4. 3/4 rebase -m: fix serialization of strategy optionsPhillip Wood, Mar 15, 2023
  5. Elijah NewrenApr 1, 2023
  6. Phillip WoodApr 4, 2023
  7. 4/4 rebase: remove a couple of redundant strategy testsPhillip Wood, Mar 15, 2023
  8. Elijah NewrenApr 1, 2023
  9. Phillip WoodApr 4, 2023
  10. Junio C HamanoMar 15, 2023
  11. Felipe ContrerasMar 15, 2023
  12. Elijah NewrenApr 1, 2023
  13. 0/5 rebase: cleanup merge strategy option handlingPhillip Wood, Apr 5, 2023
  14. 1/5 rebase: stop reading and writing unnecessary strategy statePhillip Wood, Apr 5, 2023
  15. 3/5 rebase -m: cleanup --strategy-option handlingPhillip Wood, Apr 5, 2023
  16. 2/5 sequencer: use struct strvec to store merge strategy optionsPhillip Wood, Apr 5, 2023
  17. Elijah NewrenApr 7, 2023
  18. 4/5 rebase -m: fix serialization of strategy optionsPhillip Wood, Apr 5, 2023
  19. Elijah NewrenApr 7, 2023
  20. 5/5 rebase: remove a couple of redundant strategy testsPhillip Wood, Apr 5, 2023
  21. Elijah NewrenApr 7, 2023
  22. Phillip WoodApr 7, 2023
  23. Junio C HamanoApr 7, 2023
  24. 0/5 rebase: cleanup merge strategy option handlingPhillip Wood, Apr 7, 2023
  25. 1/5 rebase: stop reading and writing unnecessary strategy statePhillip Wood, Apr 7, 2023
  26. 2/5 sequencer: use struct strvec to store merge strategy optionsPhillip Wood, Apr 7, 2023
  27. 3/5 rebase -m: cleanup --strategy-option handlingPhillip Wood, Apr 7, 2023
  28. 4/5 rebase -m: fix serialization of strategy optionsPhillip Wood, Apr 7, 2023
  29. 5/5 rebase: remove a couple of redundant strategy testsPhillip Wood, Apr 7, 2023
  30. 0/5 rebase: cleanup merge strategy option handlingPhillip Wood, Apr 10, 2023
  31. 1/5 rebase: stop reading and writing unnecessary strategy statePhillip Wood, Apr 10, 2023
  32. 3/5 rebase -m: cleanup --strategy-option handlingPhillip Wood, Apr 10, 2023
  33. 2/5 sequencer: use struct strvec to store merge strategy optionsPhillip Wood, Apr 10, 2023
  34. 4/5 rebase -m: fix serialization of strategy optionsPhillip Wood, Apr 10, 2023
  35. 5/5 rebase: remove a couple of redundant strategy testsPhillip Wood, Apr 10, 2023
  36. Elijah NewrenApr 10, 2023

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.