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

Re: [PATCH 2/5] trailer: split process_input_file into separate pieces

From
Glen Choo <chooglen@google.com>
Date
Aug 7, 2023, 22:39 UTC
Message-ID
<kl6l5y5qa34v.fsf@chooglen-macbookpro.roam.corp.google.com>
In-Reply-To
<d023c297dcac0bb96f681dc1fc0116a649c2efec.1691211879.git.gitgitgadget@gmail.com>
"Linus Arver via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 8 quoted lines
> Currently, process_input_file does three things:
>
>     (1) parse the input string for trailers,
>     (2) print text before the trailers, and
>     (3) calculate the position of the input where the trailers end.
>
> Rename this function to parse_trailers(), and make it only do
> (1).

Okay, process_input_file() is a very unhelpful name (What does it mean to "process a file"?). In contrast, parse_trailers() is more self-descriptive (It parses trailers into some appropriate format, so it shouldn't do things like print.) Makes sense.

Is there some additional, unstated purpose behind this change besides "move things around for readability"? E.g. do you intend to move parse_trailers() to a future trailer parsing library? If so, that would be useful context to evaluate the goodness of this split.

Show 5 quoted lines
> The caller of this function, process_trailers, becomes responsible
> for (2) and (3). These items belong inside process_trailers because they
> are both concerned with printing the surrounding text around
> trailers (which is already one of the immediate concerns of
> process_trailers).

I agree that (2) doesn't belong in parse_trailers(). OTOH, (3) sounds like something that belongs in parse_trailers() - you have to parse trailers in order to tell where the trailers start and end, so it makes sense for the parsing function to give those values.

Show 16 quoted lines
> diff --git a/trailer.c b/trailer.c
> index dff3fafe865..16fbba03d07 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -961,28 +961,23 @@ static void unfold_value(struct strbuf *val)
>  	strbuf_release(&out);
>  }
>  
> -static size_t process_input_file(FILE *outfile,
> -				 const char *str,
> -				 struct list_head *head,
> -				 const struct process_trailer_options *opts)
> +/*
> + * Parse trailers in "str" and populate the "head" linked list structure.
> + */
> +static void parse_trailers(struct trailer_info *info,

"info" is an out parameter, and IIRC we typically put out parameters towards the end. I didn't find a callout in CodingGuidelines, though, so idk if this is an ironclad rule or not.

Show 14 quoted lines
> +			     const char *str,
> +			     struct list_head *head,
> +			     const struct process_trailer_options *opts)
>  {
> -	struct trailer_info info;
>  	struct strbuf tok = STRBUF_INIT;
>  	struct strbuf val = STRBUF_INIT;
>  	size_t i;
>  
> -	trailer_info_get(&info, str, opts);
> -
> -	/* Print lines before the trailers as is */
> -	if (!opts->only_trailers)
> -		fwrite(str, 1, info.trailer_start - str, outfile);
We no longer fwrite the contents before the trailer, okay.
> +	trailer_info_get(info, str, opts);

This is where we actually get the start and end of trailers, and each trailer string. This is parsing out the trailers from a string, so what other parsing is left? Reading ahead shows that we're actually parsing the trailer string into a "struct trailer_item". Okay, so this function is basically a wrapper around trailer_info_get() that also "returns" the parsed trailer_items.

> -	if (!opts->only_trailers && !info.blank_line_before_trailer)
> -		fprintf(outfile, "\n");
> -
So we don't print the trailing line. Also makes sense.
Show 10 quoted lines
> @@ -1003,9 +998,7 @@ static size_t process_input_file(FILE *outfile,
>  		}
>  	}
>  
> -	trailer_info_release(&info);
> -
> -	return info.trailer_end - str;
> +	trailer_info_release(info);
>  }
>  

Even though "info" is a pointer passed into this function, we are _release-ing it. This is not an umabiguously good change, IMO. Before, "info" was never used outside of this function, so we should obviously release it before returning. However, now that "info" is an out parameter, we should be more careful about releasing it. I don't think it's obvious that the caller will see the right values for info.trailer_end and info.trailer_start, but free()-d values for info.trailers, and a meaningless value for info.trailer_nr (since the items were free()-d).

I think it might be better to update the comment on parse_trailers() like so:

  /*
   * Parse trailers in "str", populating the trailer info and "head"
   * linked list structure.
   */

and make it the caller's responsibility to call trailer_info_release(). We could move this call to where we "free_all(head)".

Show 12 quoted lines
>  static void free_all(struct list_head *head)
> @@ -1054,6 +1047,7 @@ void process_trailers(const char *file,
>  {
>  	LIST_HEAD(head);
>  	struct strbuf sb = STRBUF_INIT;
> +	struct trailer_info info;
>  	size_t trailer_end;
>  	FILE *outfile = stdout;
>  
> @@ -1064,8 +1058,16 @@ void process_trailers(const char *file,
>  	if (opts->in_place)
>  		outfile = create_in_place_tempfile(file);

Thinking out loud, should we move the creation of outfile next to where we first use it?

Show 7 quoted lines
> +	parse_trailers(&info, sb.buf, &head, opts);
> +	trailer_end = info.trailer_end - sb.buf;
> +
>  	/* Print the lines before the trailers */
> -	trailer_end = process_input_file(outfile, sb.buf, &head, opts);
> +	if (!opts->only_trailers)
> +		fwrite(sb.buf, 1, info.trailer_start - sb.buf, outfile);

I'm not sure if it is an unambiguously good change for the caller to learn how to compute the start and end of the trailer sections by doing pointer arithmetic, but I guess format_trailer_info() does this anyway, so your proposal to move (3) outside of the parse_trailers() makes sense.

It feels a bit non-obvious that trailer_start and trailer_end are pointing inside the input string. I wonder if we should just return the _start and _end offsets directly instead of returning pointers. I.e.:

   struct trailer_info {
     int blank_line_before_trailer;
 -  /*
 -   * Pointers to the start and end of the trailer block found. If there
 -   * is no trailer block found, these 2 pointers point to the end of the
 -   * input string.
 -   */
 -   const char *trailer_start, *trailer_end;
 +   /* Offsets to the trailer block start and end in the input string */
 +   size_t *trailer_start, *trailer_end;

Which makes their intended use fairly unambiguous. A quick grep suggests that in trailer.c, we're roughly as likely to use the pointer directly vs using it to do pointer arithmetic, so converging on one use might be a win for readability. The only other user outside of trailer.c is sequencer.c, which doesn't care about the return type - it only checks if there are trailers.

Previous: Linus Arver via GitGitGadgetNext: Linus Arver
Message 8 of 72 in “Trailer readability cleanups”
  1. 0/5 Trailer readability cleanupsLinus Arver via GitGitGadget, Aug 5, 2023
  2. 1/5 trailer: separate public from internal portion of trailer_iteratorLinus Arver via GitGitGadget, Aug 5, 2023
  3. Glen ChooAug 7, 2023
  4. Phillip WoodAug 8, 2023
  5. Linus ArverAug 10, 2023
  6. Linus ArverAug 10, 2023
  7. 2/5 trailer: split process_input_file into separate piecesLinus Arver via GitGitGadget, Aug 5, 2023
  8. Glen ChooAug 7, 2023
  9. Linus ArverAug 11, 2023
  10. 4/5 trailer: teach find_patch_start about --no-dividerLinus Arver via GitGitGadget, Aug 5, 2023
  11. Glen ChooAug 7, 2023
  12. Linus ArverAug 11, 2023
  13. Glen ChooAug 11, 2023
  14. 3/5 trailer: split process_command_line_args into separate functionsLinus Arver via GitGitGadget, Aug 5, 2023
  15. Glen ChooAug 7, 2023
  16. Linus ArverAug 11, 2023
  17. Linus ArverAug 11, 2023
  18. Glen ChooAug 11, 2023
  19. 5/5 trailer: rename *_DEFAULT enums to *_UNSPECIFIEDLinus Arver via GitGitGadget, Aug 5, 2023
  20. Glen ChooAug 7, 2023
  21. Linus ArverAug 11, 2023
  22. 0/6 Trailer readability cleanupsLinus Arver via GitGitGadget, Sep 9, 2023
  23. 1/6 trailer: separate public from internal portion of trailer_iteratorLinus Arver via GitGitGadget, Sep 9, 2023
  24. Junio C HamanoSep 11, 2023
  25. 2/6 trailer: split process_input_file into separate piecesLinus Arver via GitGitGadget, Sep 9, 2023
  26. Junio C HamanoSep 11, 2023
  27. 3/6 trailer: split process_command_line_args into separate functionsLinus Arver via GitGitGadget, Sep 9, 2023
  28. 4/6 trailer: teach find_patch_start about --no-dividerLinus Arver via GitGitGadget, Sep 9, 2023
  29. Junio C HamanoSep 11, 2023
  30. Linus ArverSep 14, 2023
  31. Junio C HamanoSep 14, 2023
  32. Linus ArverSep 14, 2023
  33. 6/6 trailer: use offsets for trailer_start/trailer_endLinus Arver via GitGitGadget, Sep 9, 2023
  34. Junio C HamanoSep 11, 2023
  35. Linus ArverSep 14, 2023
  36. Linus ArverSep 14, 2023
  37. 5/6 trailer: rename *_DEFAULT enums to *_UNSPECIFIEDLinus Arver via GitGitGadget, Sep 9, 2023
  38. Junio C HamanoSep 11, 2023
  39. Linus ArverSep 14, 2023
  40. Junio C HamanoSep 14, 2023
  41. Linus ArverSep 22, 2023
  42. Junio C HamanoSep 22, 2023
  43. Linus ArverSep 26, 2023
  44. 0/9 Trailer readability cleanupsLinus Arver via GitGitGadget, Sep 22, 2023
  45. 1/9 trailer: separate public from internal portion of trailer_iteratorLinus Arver via GitGitGadget, Sep 22, 2023
  46. 2/9 trailer: split process_input_file into separate piecesLinus Arver via GitGitGadget, Sep 22, 2023
  47. 3/9 trailer: split process_command_line_args into separate functionsLinus Arver via GitGitGadget, Sep 22, 2023
  48. 4/9 trailer: rename *_DEFAULT enums to *_UNSPECIFIEDLinus Arver via GitGitGadget, Sep 22, 2023
  49. 5/9 commit: ignore_non_trailer computes number of bytes to ignoreLinus Arver via GitGitGadget, Sep 22, 2023
  50. 6/9 trailer: find the end of the log messageLinus Arver via GitGitGadget, Sep 22, 2023
  51. 9/9 trailer: make stack variable names match field namesLinus Arver via GitGitGadget, Sep 22, 2023
  52. 7/9 trailer: use offsets for trailer_start/trailer_endLinus Arver via GitGitGadget, Sep 22, 2023
  53. 8/9 trailer: only use trailer_block_* variables if trailers were foundLinus Arver via GitGitGadget, Sep 22, 2023
  54. Junio C HamanoSep 22, 2023
  55. Linus ArverSep 22, 2023
  56. Junio C HamanoSep 23, 2023
  57. Linus ArverSep 26, 2023
  58. 0/4 Trailer readability cleanupsLinus Arver via GitGitGadget, Sep 26, 2023
  59. 1/4 commit: ignore_non_trailer computes number of bytes to ignoreLinus Arver via GitGitGadget, Sep 26, 2023
  60. 2/4 trailer: find the end of the log messageLinus Arver via GitGitGadget, Sep 26, 2023
  61. Jonathan TanSep 28, 2023
  62. Linus ArverOct 20, 2023
  63. Junio C HamanoOct 20, 2023
  64. 3/4 trailer: use offsets for trailer_start/trailer_endLinus Arver via GitGitGadget, Sep 26, 2023
  65. 4/4 trailer: only use trailer_block_* variables if trailers were foundLinus Arver via GitGitGadget, Sep 26, 2023
  66. 0/3 Trailer readability cleanupsLinus Arver via GitGitGadget, Oct 20, 2023
  67. 1/3 commit: ignore_non_trailer computes number of bytes to ignoreLinus Arver via GitGitGadget, Oct 20, 2023
  68. 2/3 trailer: find the end of the log messageLinus Arver via GitGitGadget, Oct 20, 2023
  69. Junio C HamanoOct 20, 2023
  70. Linus ArverDec 29, 2023
  71. Linus ArverDec 29, 2023
  72. 3/3 trailer: use offsets for trailer_start/trailer_endLinus Arver via GitGitGadget, Oct 20, 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.