Re: [PATCH 3/4] rebase -m: fix serialization of strategy options
- From
Elijah Newren <newren@gmail.com>
- Date
- Apr 1, 2023, 19:27 UTC
- Message-ID
- <CABPp-BF6_gmDCTo5j2fR5_KQfJYVuYZuYv6TdhsMvPYshXzu+g@mail.gmail.com>
- In-Reply-To
- <9af68cb065871d9b89e99ef6b48870d322bb5faa.1678893298.git.phillip.wood@dunelm.org.uk>
On Wed, Mar 15, 2023 at 8:51 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 20 quoted lines
> > 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.
I'm not sure we want to tie ourselves to support completing a rebase with git version X+1 that was started with git version X. But, it's really nice that you're paying attention to that level of detail. :-)
Show 49 quoted lines
>
> 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, '"');
> + }Do we not have a function in quote.[ch] that can handle this? If not, should we add this code to a function in that file and call it?
Show 57 quoted lines
> 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
> 'I appreciate the more stringent test to cover these new special cases. :-)
Show 39 quoted lines
> > 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