Show 190 quoted lines
> 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>
> ---
> alias.c | 18 +++++++++++++++++
> alias.h | 3 +++
> sequencer.c | 11 ++++++-----
> t/t3418-rebase-continue.sh | 36 ++++++++++++++++++++++------------
> t/t3436-rebase-more-options.sh | 24 -----------------------
> 5 files changed, 50 insertions(+), 42 deletions(-)
>
> diff --git a/alias.c b/alias.c
> index e814948ced..54a1a23d2c 100644
> --- a/alias.c
> +++ b/alias.c
> @@ -3,6 +3,7 @@
> #include "alloc.h"
> #include "config.h"
> #include "gettext.h"
> +#include "strbuf.h"
> #include "string-list.h"
>
> struct config_alias_data {
> @@ -46,6 +47,23 @@ void list_aliases(struct string_list *list)
> read_early_config(config_alias_cb, &data);
> }
>
> +void quote_cmdline(struct strbuf *buf, const char **argv)
> +{
> + for (const char **argp = argv; *argp; argp++) {
> + if (argp != argv)
> + strbuf_addch(buf, ' ');
> + strbuf_addch(buf, '"');
> + for (const char *p = *argp; *p; p++) {
> + const char c = *p;
> +
> + if (c == '"' || c =='\\')
> + strbuf_addch(buf, '\\');
> + strbuf_addch(buf, c);
> + }
> + strbuf_addch(buf, '"');
> + }
> +}
> +
> #define SPLIT_CMDLINE_BAD_ENDING 1
> #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
> #define SPLIT_CMDLINE_ARGC_OVERFLOW 3
> diff --git a/alias.h b/alias.h
> index aef4843bb7..43db736484 100644
> --- a/alias.h
> +++ b/alias.h
> @@ -1,9 +1,12 @@
> #ifndef ALIAS_H
> #define ALIAS_H
>
> +struct strbuf;
> struct string_list;
>
> char *alias_lookup(const char *alias);
> +/* Quote argv so buf can be parsed by split_cmdline() */
> +void quote_cmdline(struct strbuf *buf, const char **argv);
> int split_cmdline(char *cmdline, const char ***argv);
> /* Takes a negative value returned by split_cmdline */
> const char *split_cmdline_strerror(int cmdline_errno);
> diff --git a/sequencer.c b/sequencer.c
> index 045d549042..9907100c8a 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -2925,7 +2925,7 @@ static void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
>
> count = split_cmdline(strategy_opts_string, &argv);
> 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));
> for (i = 0; i < count; i++) {
> const char *arg = argv[i];
> @@ -3048,12 +3048,13 @@ 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.v[i]);
> -
> + /*
> + * Quote strategy options so that they can be read correctly
> + * by split_cmdline().
> + */
> + quote_cmdline(&buf, opts->xopts.v);
> 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 "\$@"
> - EOF
> - chmod +x test-bin/git-merge-funny &&
> +
> + write_script test-bin/git-merge-funny <<-\EOF &&
> + printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual
> + shift 3 &&
> + exec git merge-recursive "$@"
> + EOF
> +
> + 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.40.0.670.g64ef305212.dirty