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

Re: [PATCH 3/3] sequencer: use read_author_script()

From
PWPhillip Wood <phillip.wood@talktalk.net>
Date
Oct 10, 2018, 10:35 UTC
Message-ID
<2a8e3ea2-d97f-5e03-e4c7-4badb11e69b9@talktalk.net>
In-Reply-To
<CAPig+cS8ncvp8Se2Q24z9CFkiVey2zHP8i3oYVDPfGoP1kuDdA@mail.gmail.com>
On 14/09/2018 01:31, Eric Sunshine wrote:
Show 35 quoted lines
> On Wed, Sep 12, 2018 at 6:11 AM Phillip Wood <phillip.wood@talktalk.net> wrote:
>> Use the new function to read the author script, updating
>> read_env_script() and read_author_ident(). This means we now have a
>> single code path that reads the author script and uses sq_dequote() to
>> dequote it. This fixes potential problems with user edited scripts
>> as read_env_script() which did not track quotes properly.
>> [...]
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>  /*
>>   * Read a list of environment variable assignments (such as the author-script
>>   * file) into an environment block. Returns -1 on error, 0 otherwise.
>>   */
> 
> According to this comment, this function is capable of parsing a file
> of arbitrary "NAME=Value" lines, and indeed the original code does
> just that, but...
> 
>>  static int read_env_script(struct argv_array *env)
>>  {
>> +       char *name, *email, *date;
>>
>> -       if (strbuf_read_file(&script, rebase_path_author_script(), 256) <= 0)
>> +       if (read_author_script(rebase_path_author_script(),
>> +                              &name, &email, &date, 0))
> 
> ...the new implementation is able to handle only GIT_AUTHOR_NAME,
> GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE, in exactly that order.
> 
> This seems like a pretty serious (and possibly buggy) change of
> behavior, and makes the function much less useful (in general). Is it
> true that it will only ever be used for files containing that limited
> set of names? If so, the behavior change deserves mention in the
> commit message, the function comment needs updating, and the function
> itself probably ought to be renamed.

You're right the change in behavior should be mentioned explicitly, I'd not thought about it in those terms. I'm not sure if the change is buggy, this code is what am uses for its author script handling. To me the point of the author-script file is to set the author details, not to set arbitrary environment variables. We have already significantly reduced what someone can do with this file in the transition from shell to C as we no longer support arbitrary shell code in the file. I'd rather try and reuse the existing code from am unless someone can demonstrate an active use for something more general. (I'm still not sure what use editing the author-script is - it is only of use if the rebase stops for conflicts, it cannot be used to change the author of an arbitrary set of commits)

Show 38 quoted lines
>> +       strbuf_addstr(&script, "GIT_AUTHOR_NAME=");
>> +       strbuf_addstr(&script, name);
>> +       argv_array_push(env, script.buf);
>> +       strbuf_reset(&script);
>> +       strbuf_addstr(&script, "GIT_AUTHOR_EMAIL=");
>> +       strbuf_addstr(&script, email);
>> +       argv_array_push(env, script.buf);
>> +       strbuf_reset(&script);
>> +       strbuf_addstr(&script, "GIT_AUTHOR_DATE=");
>> +       strbuf_addstr(&script, date);
>> +       argv_array_push(env, script.buf);
>> +       strbuf_release(&script);
> 
> Mentioned earlier[1], this can all collapse down to:
> 
> argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
> argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
> argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
> 
> However, it's unfortunate that this manual and hard-coded
> reconstruction is needed at all. If you restructure the factoring of
> this patch series, such ugliness can be avoided altogether. For
> instance, the series could be structured like this:
> 
> 1. Introduce a general-purpose function for reading a file containing
> arbitrary "NAME=Value" lines (not carrying about specific key names or
> their order) and returning them in some data structure (perhaps via
> 'string_list' as parse_key_value_squoted() in patch 2/3 does).
> 
> 2. Build read_author_script() atop #1, making it expect and extract
> GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and GIT_AUTHOR_DATE (possibly in
> that order, or possibly not if we don't care).
> 
> 3. Retrofit existing parsers to call one of those two functions (this
> step may happen over several patches). So, for instance,
> read_env_script() would call the generic parser from #1, whereas
> sequencer.c:read_author_ident() would call the more specific parser
> from #2.

That plan requires all new code rather than reusing tried and tested code from am. Furthermore I'm not sure it has any advantage as far as users are concerned. My aim with this series was to try and do something fairly simple that reused the parsing from am, rather than build a whole new system with its own bugs.

Show 39 quoted lines
> More below...
> 
>> @@ -790,54 +771,25 @@ static char *get_author(const char *message)
>>  /* Read author-script and return an ident line (author <email> timestamp) */
>>  static const char *read_author_ident(struct strbuf *buf)
>>  {
>> -       const char *keys[] = {
>> -               "GIT_AUTHOR_NAME=", "GIT_AUTHOR_EMAIL=", "GIT_AUTHOR_DATE="
>> -       };
>> -       if (strbuf_read_file(buf, rebase_path_author_script(), 256) <= 0)
>> +       if (read_author_script(rebase_path_author_script(),
>> +                              &name, &email, &date, 0))
>>                 return NULL;
>> -       /* dequote values and construct ident line in-place */
>> -       for (in = buf->buf; i < 3 && in - buf->buf < buf->len; i++) {
>> -               if (!skip_prefix(in, keys[i], (const char **)&in)) {
>> -                       warning(_("could not parse '%s' (looking for '%s')"),
>> -                               rebase_path_author_script(), keys[i]);
>> -                       return NULL;
>> -               }
>> -               if (!sq_dequote(in)) {
>> -                       warning(_("bad quoting on %s value in '%s'"),
>> -                               keys[i], rebase_path_author_script());
>> -                       return NULL;
>> -               }
>> -       if (i < 3) {
>> -               warning(_("could not parse '%s' (looking for '%s')"),
>> -                       rebase_path_author_script(), keys[i]);
>> -               return NULL;
>> -       }
> 
> The parsing code being thrown away here does a better job of
> diagnosing problems (thus helping the user figure out what went wrong)
> than the new shared parser introduced by patch 2/3. The shared
> function only ever reports a generic "unable to parse", whereas the
> above code gets specific, saying that it was looking for a particular
> key or that quoting was broken. I'd have expected the new shared
> parser to encompass the best features of the existing parsers (such as
> presenting better error messages).

You're right but the context is that this function is only used when the root commit is rebased (and then only for the root commit). Everything else goes through read_env_script() which doesn't even bother to check if all the variables have been set or report any parsing errors.

Show 10 quoted lines
> 
>>         /* validate date since fmt_ident() will die() on bad value */
>> -       if (parse_date(val[2], &out)){
>> +       if (parse_date(date, buf)){
> 
> Re-purposing the strbuf 'buf', which is passed into this function,
> binds this function too tightly with its caller by assuming that the
> caller will never need the original content of 'buf' anymore. Thus, it
> would be better for this code continue using its own local strbuf
> 'out' rather than re-purposing the incoming 'buf'.
That's a good point, I'll fix it.
Show 14 quoted lines
>>                 warning(_("invalid date format '%s' in '%s'"),
>> -                       val[2], rebase_path_author_script());
>> -               strbuf_release(&out);
>> +                       date, rebase_path_author_script());
>> +               strbuf_release(buf);
> 
> Likewise, it's doubly odd to see this function releasing 'buf' which
> it does not own.
> 
>>                 return NULL;
>>         }
> 
> [1]: https://public-inbox.org/git/CAPig+cRvUr26GZyW6ecYhpwABueBqaEfZH1+JjLaqZo8+RTD6Q@mail.gmail.com/
> 

Thanks for looking at this, I'm keen to keep things simple and reuse the am author-script parsing if possible. It is more restrictive but I'm not sure that anyone is actually taking advantage of the flexibility offered by the current setup and it fixes the de-quoting bugs in read_env_script().

Best Wishes
Phillip
Previous: Eric SunshineNext: Phillip Wood
Message 10 of 41 in “am/rebase: share read_author_script()”
  1. 0/3 am/rebase: share read_author_script()Phillip Wood, Sep 12, 2018
  2. 1/3 am: rename read_author_script()Phillip Wood, Sep 12, 2018
  3. 2/3 add read_author_script() to libgitPhillip Wood, Sep 12, 2018
  4. Eric SunshineSep 13, 2018
  5. Phillip WoodOct 10, 2018
  6. Eric SunshineOct 10, 2018
  7. 3/3 sequencer: use read_author_script()Phillip Wood, Sep 12, 2018
  8. Eric SunshineSep 12, 2018
  9. Eric SunshineSep 14, 2018
  10. Phillip WoodOct 10, 2018
  11. 0/5 am/rebase: share read_author_script()Phillip Wood, Oct 18, 2018
  12. 1/5 am: don't die in read_author_script()Phillip Wood, Oct 18, 2018
  13. Junio C HamanoOct 25, 2018
  14. 2/5 am: improve author-script error reportingPhillip Wood, Oct 18, 2018
  15. Junio C HamanoOct 25, 2018
  16. 3/5 am: rename read_author_script()Phillip Wood, Oct 18, 2018
  17. 5/5 sequencer: use read_author_script()Phillip Wood, Oct 18, 2018
  18. 4/5 add read_author_script() to libgitPhillip Wood, Oct 18, 2018
  19. Junio C HamanoOct 25, 2018
  20. Phillip WoodOct 26, 2018
  21. Junio C HamanoOct 26, 2018
  22. 0/5 am/rebase: share read_author_script()Phillip Wood, Oct 30, 2018
  23. 2/5 am: improve author-script error reportingPhillip Wood, Oct 30, 2018
  24. 1/5 am: don't die in read_author_script()Phillip Wood, Oct 30, 2018
  25. 4/5 add read_author_script() to libgitPhillip Wood, Oct 30, 2018
  26. 5/5 sequencer: use read_author_script()Phillip Wood, Oct 30, 2018
  27. 3/5 am: rename read_author_script()Phillip Wood, Oct 30, 2018
  28. Junio C HamanoOct 31, 2018
  29. Phillip WoodOct 31, 2018
  30. 0/5 am/rebase: share read_author_script()Phillip Wood, Oct 31, 2018
  31. 2/5 am: improve author-script error reportingPhillip Wood, Oct 31, 2018
  32. Eric SunshineNov 4, 2018
  33. Junio C HamanoNov 5, 2018
  34. 3/5 am: rename read_author_script()Phillip Wood, Oct 31, 2018
  35. 5/5 sequencer: use read_author_script()Phillip Wood, Oct 31, 2018
  36. 4/5 add read_author_script() to libgitPhillip Wood, Oct 31, 2018
  37. 1/5 am: don't die in read_author_script()Phillip Wood, Oct 31, 2018
  38. Junio C HamanoNov 1, 2018
  39. 2/5 am: improve author-script error reportingJunio C Hamano, Nov 1, 2018
  40. 4/5 add read_author_script() to libgitJunio C Hamano, Nov 1, 2018
  41. Phillip WoodNov 1, 2018

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.