Re: [PATCH v2 4/5] rebase -m: fix serialization of strategy options

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 5, 2023 at 8:22 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,

s/be still be/still be/

Sorry for not noticing this last time.

> 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@xxxxxxxxxxxxx>
> ---
>  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

Looks good.




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux