On Wed, Mar 15, 2023 at 8:51 AM Phillip Wood <phillip.wood123@xxxxxxxxx> wrote: > > From: Phillip Wood <phillip.wood@xxxxxxxxxxxxx> > > 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. :-) > > Signed-off-by: Phillip Wood <phillip.wood@xxxxxxxxxxxxx> > --- > 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? > 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. :-) > > 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