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

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

From
Elijah Newren <newren@gmail.com>
Date
Apr 7, 2023, 05:47 UTC
Message-ID
<CABPp-BGPyVZu1iOW5TLUE+tfU+uFs=UNNzFX+=DFY5D2Wt4-+w@mail.gmail.com>
In-Reply-To
<9a90212ef284510fa691b8eebd6bdd61098282fd.1680708043.git.phillip.wood@dunelm.org.uk>
On Wed, Apr 5, 2023 at 8:22 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 18 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,
s/be still be/still be/
Sorry for not noticing this last time.
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
Looks good.
Previous: Phillip WoodNext: Phillip Wood
Message 19 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.