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

[PATCH v4 19/28] trailer: make trailer_info struct private

From
LGLinus Arver via GitGitGadget <gitgitgadget@gmail.com>
Date
Feb 6, 2024, 05:12 UTC
Message-ID
<f5f0d06613f2701af9bd3a1a9274aae232e03d8f.1707196348.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1632.v4.git.1707196348.gitgitgadget@gmail.com>
From: Linus Arver <linusa@google.com>

In 13211ae23f (trailer: separate public from internal portion of trailer_iterator, 2023-09-09) we moved trailer_info behind an anonymous struct to discourage use by trailer.h API users. However it still left open the possibility of external use of trailer_info itself. Now that there are no external users of trailer_info, we can make this struct private.

Make this struct private by putting its definition inside trailer.c. This has two benefits:

  (1) it makes the surface area of the public facing
      interface (trailer.h) smaller, and
  (2) external API users are unable to peer inside this struct (because
      it is only ever exposed as an opaque pointer).
There are a couple disadvantages:
  (A) every time the member of the struct is accessed an extra pointer
      dereference must be done, and
  (B) for users of trailer_info outside trailer.c, this struct can no
      longer be allocated on the stack and may only be allocated on the
      heap (because its definition is hidden away in trailer.c) and
      appropriately deallocated by the user.

This patch believes that the benefits outweight the advantages for designing APIs, as explained below.

Making trailer_info private exposes existing deficiencies in the API. This is because users of this struct had full access to its internals, so there wasn't much need to actually design it to be "complete" in the sense that API users only needed to use what was provided by the API. For example, the location of the trailer block (start/end offsets relative to the start of the input text) was accessible by looking at these struct members directly. Now that the struct is private, we have to expose new API functions to allow clients to access this information (see builtin/interpret-trailers.c).

The idea in this patch to hide implementation details behind an "opaque pointer" is also known as the "pimpl" (pointer to implementation) idiom in C++ and is a common pattern in that language (where, for example, abstract classes only have pointers to concrete classes).

However, the original inspiration to use this idiom does not come from C++, but instead the book "C Interfaces and Implementations: Techniques for Creating Reusable Software" [1]. This book recommends opaque pointers as a good design principle for designing C libraries, using the term "interface" as the functions defined in *.h (header) files and "implementation" as the corresponding *.c file which define the interfaces.

The book says this about opaque pointers:
    ... clients can manipulate such pointers freely, but they can’t
    dereference them; that is, they can’t look at the innards of the
    structure pointed to by them. Only the implementation has that
    privilege. Opaque pointers hide representation details and help
    catch errors.

In our case, "struct trailer_info" is now hidden from clients, and the ways in which this opaque pointer can be used is limited to the richness of <trailer.h>. In other words, <trailer.h> exclusively controls exactly how "trailer_info" pointers are to be used.

[1] Hanson, David R. "C Interfaces and Implementations: Techniques for
    Creating Reusable Software". Addison Wesley, 1997. p. 22
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Linus Arver <linusa@google.com>
---
 builtin/interpret-trailers.c | 12 +++---
 trailer.c                    | 81 ++++++++++++++++++++++++++++--------
 trailer.h                    | 40 +++++-------------
 3 files changed, 80 insertions(+), 53 deletions(-)
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 11f4ce9e4a2..6bf8cec005a 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -141,7 +141,7 @@ static void interpret_trailers(const struct process_trailer_options *opts,
 	LIST_HEAD(head);
 	struct strbuf sb = STRBUF_INIT;
 	struct strbuf trailer_block = STRBUF_INIT;
-	struct trailer_info info;
+	struct trailer_info *info;
 	FILE *outfile = stdout;
 
 	trailer_config_init();
@@ -151,13 +151,13 @@ static void interpret_trailers(const struct process_trailer_options *opts,
 	if (opts->in_place)
 		outfile = create_in_place_tempfile(file);
 
-	parse_trailers(opts, &info, sb.buf, &head);
+	info = parse_trailers(opts, sb.buf, &head);
 
 	/* Print the lines before the trailers */
 	if (!opts->only_trailers)
-		fwrite(sb.buf, 1, info.trailer_block_start, outfile);
+		fwrite(sb.buf, 1, trailer_block_start(info), outfile);
 
-	if (!opts->only_trailers && !info.blank_line_before_trailer)
+	if (!opts->only_trailers && !blank_line_before_trailer_block(info))
 		fprintf(outfile, "\n");
 
 
@@ -178,8 +178,8 @@ static void interpret_trailers(const struct process_trailer_options *opts,
 
 	/* Print the lines after the trailers as is */
 	if (!opts->only_trailers)
-		fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile);
-	trailer_info_release(&info);
+		fwrite(sb.buf + trailer_block_end(info), 1, sb.len - trailer_block_end(info), outfile);
+	trailer_info_release(info);
 
 	if (opts->in_place)
 		if (rename_tempfile(&trailers_tempfile, file))
diff --git a/trailer.c b/trailer.c
index 2cc4a910411..cc211dfeeae 100644
--- a/trailer.c
+++ b/trailer.c
@@ -11,6 +11,27 @@
  * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
  */
 
+struct trailer_info {
+	/*
+	 * True if there is a blank line before the location pointed to by
+	 * trailer_block_start.
+	 */
+	int blank_line_before_trailer;
+
+	/*
+	 * Offsets to the trailer block start and end positions in the input
+	 * string. If no trailer block is found, these are both set to the
+	 * "true" end of the input (find_end_of_log_message()).
+	 */
+	size_t trailer_block_start, trailer_block_end;
+
+	/*
+	 * Array of trailers found.
+	 */
+	char **trailers;
+	size_t trailer_nr;
+};
+
 struct conf_info {
 	char *name;
 	char *key;
@@ -953,20 +974,26 @@ static void unfold_value(struct strbuf *val)
 	strbuf_release(&out);
 }
 
+static struct trailer_info *trailer_info_new(void)
+{
+	struct trailer_info *info = xcalloc(1, sizeof(*info));
+	return info;
+}
+
 /*
  * Parse trailers in "str", populating the trailer info and "head"
  * linked list structure.
  */
-void parse_trailers(const struct process_trailer_options *opts,
-		    struct trailer_info *info,
-		    const char *str,
-		    struct list_head *head)
+struct trailer_info *parse_trailers(const struct process_trailer_options *opts,
+				    const char *str,
+				    struct list_head *head)
 {
+	struct trailer_info *info;
 	struct strbuf tok = STRBUF_INIT;
 	struct strbuf val = STRBUF_INIT;
 	size_t i;
 
-	trailer_info_get(opts, str, info);
+	info = trailer_info_get(opts, str);
 
 	for (i = 0; i < info->trailer_nr; i++) {
 		int separator_pos;
@@ -990,6 +1017,8 @@ void parse_trailers(const struct process_trailer_options *opts,
 					 strbuf_detach(&val, NULL));
 		}
 	}
+
+	return info;
 }
 
 void free_trailers(struct list_head *trailers)
@@ -1001,10 +1030,25 @@ void free_trailers(struct list_head *trailers)
 	}
 }
 
-void trailer_info_get(const struct process_trailer_options *opts,
-		      const char *str,
-		      struct trailer_info *info)
+size_t trailer_block_start(struct trailer_info *info)
+{
+	return info->trailer_block_start;
+}
+
+size_t trailer_block_end(struct trailer_info *info)
+{
+	return info->trailer_block_end;
+}
+
+int blank_line_before_trailer_block(struct trailer_info *info)
+{
+	return info->blank_line_before_trailer;
+}
+
+struct trailer_info *trailer_info_get(const struct process_trailer_options *opts,
+				      const char *str)
 {
+	struct trailer_info *info = trailer_info_new();
 	size_t end_of_log_message = 0, trailer_block_start = 0;
 	struct strbuf **trailer_lines, **ptr;
 	char **trailer_strings = NULL;
@@ -1043,6 +1087,8 @@ void trailer_info_get(const struct process_trailer_options *opts,
 	info->trailer_block_end = end_of_log_message;
 	info->trailers = trailer_strings;
 	info->trailer_nr = nr;
+
+	return info;
 }
 
 void trailer_info_release(struct trailer_info *info)
@@ -1051,6 +1097,7 @@ void trailer_info_release(struct trailer_info *info)
 	for (i = 0; i < info->trailer_nr; i++)
 		free(info->trailers[i]);
 	free(info->trailers);
+	free(info);
 }
 
 void format_trailers(const struct process_trailer_options *opts,
@@ -1118,21 +1165,19 @@ void format_trailers_from_commit(const struct process_trailer_options *opts,
 				 struct strbuf *out)
 {
 	LIST_HEAD(trailers);
-	struct trailer_info info;
-
-	parse_trailers(opts, &info, msg, &trailers);
+	struct trailer_info *info = parse_trailers(opts, msg, &trailers);
 
 	/* If we want the whole block untouched, we can take the fast path. */
 	if (!opts->only_trailers && !opts->unfold && !opts->filter &&
 	    !opts->separator && !opts->key_only && !opts->value_only &&
 	    !opts->key_value_separator) {
-		strbuf_add(out, msg + info.trailer_block_start,
-			   info.trailer_block_end - info.trailer_block_start);
+		strbuf_add(out, msg + info->trailer_block_start,
+			   info->trailer_block_end - info->trailer_block_start);
 	} else
 		format_trailers(opts, &trailers, out);
 
 	free_trailers(&trailers);
-	trailer_info_release(&info);
+	trailer_info_release(info);
 }
 
 void trailer_iterator_init(struct trailer_iterator *iter, const char *msg)
@@ -1141,14 +1186,14 @@ void trailer_iterator_init(struct trailer_iterator *iter, const char *msg)
 	strbuf_init(&iter->key, 0);
 	strbuf_init(&iter->val, 0);
 	opts.no_divider = 1;
-	trailer_info_get(&opts, msg, &iter->internal.info);
+	iter->internal.info = trailer_info_get(&opts, msg);
 	iter->internal.cur = 0;
 }
 
 int trailer_iterator_advance(struct trailer_iterator *iter)
 {
-	if (iter->internal.cur < iter->internal.info.trailer_nr) {
-		char *line = iter->internal.info.trailers[iter->internal.cur++];
+	if (iter->internal.cur < iter->internal.info->trailer_nr) {
+		char *line = iter->internal.info->trailers[iter->internal.cur++];
 		int separator_pos = find_separator(line, separators);
 
 		iter->raw = line;
@@ -1165,7 +1210,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter)
 
 void trailer_iterator_release(struct trailer_iterator *iter)
 {
-	trailer_info_release(&iter->internal.info);
+	trailer_info_release(iter->internal.info);
 	strbuf_release(&iter->val);
 	strbuf_release(&iter->key);
 }
diff --git a/trailer.h b/trailer.h
index ebafa3657e4..a63e97a2663 100644
--- a/trailer.h
+++ b/trailer.h
@@ -4,6 +4,8 @@
 #include "list.h"
 #include "strbuf.h"
 
+struct trailer_info;
+
 enum trailer_where {
 	WHERE_DEFAULT,
 	WHERE_END,
@@ -29,27 +31,6 @@ int trailer_set_where(enum trailer_where *item, const char *value);
 int trailer_set_if_exists(enum trailer_if_exists *item, const char *value);
 int trailer_set_if_missing(enum trailer_if_missing *item, const char *value);
 
-struct trailer_info {
-	/*
-	 * True if there is a blank line before the location pointed to by
-	 * trailer_block_start.
-	 */
-	int blank_line_before_trailer;
-
-	/*
-	 * Offsets to the trailer block start and end positions in the input
-	 * string. If no trailer block is found, these are both set to the
-	 * "true" end of the input (find_end_of_log_message()).
-	 */
-	size_t trailer_block_start, trailer_block_end;
-
-	/*
-	 * Array of trailers found.
-	 */
-	char **trailers;
-	size_t trailer_nr;
-};
-
 /*
  * A list that represents newly-added trailers, such as those provided
  * with the --trailer command line option of git-interpret-trailers.
@@ -89,14 +70,15 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head,
 void process_trailers_lists(struct list_head *head,
 			    struct list_head *arg_head);
 
-void parse_trailers(const struct process_trailer_options *,
-		    struct trailer_info *,
-		    const char *str,
-		    struct list_head *head);
+struct trailer_info *parse_trailers(const struct process_trailer_options *,
+				    const char *str,
+				    struct list_head *head);
+struct trailer_info *trailer_info_get(const struct process_trailer_options *,
+				      const char *str);
 
-void trailer_info_get(const struct process_trailer_options *,
-		      const char *str,
-		      struct trailer_info *);
+size_t trailer_block_start(struct trailer_info *);
+size_t trailer_block_end(struct trailer_info *);
+int blank_line_before_trailer_block(struct trailer_info *);
 
 void trailer_info_release(struct trailer_info *info);
 
@@ -138,7 +120,7 @@ struct trailer_iterator {
 
 	/* private */
 	struct {
-		struct trailer_info info;
+		struct trailer_info *info;
 		size_t cur;
 	} internal;
 };
-- 
gitgitgadget
Previous: Linus Arver via GitGitGadgetNext: Junio C Hamano
Message 131 of 202 in “Enrich Trailer API”
  1. 00/10 Enrich Trailer APILinus Arver via GitGitGadget, Jan 10, 2024
  2. 01/10 trailer: move process_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Jan 10, 2024
  3. Junio C HamanoJan 18, 2024
  4. Linus ArverJan 19, 2024
  5. 02/10 trailer: include "trailer" term in API functionsLinus Arver via GitGitGadget, Jan 10, 2024
  6. Junio C HamanoJan 18, 2024
  7. Linus ArverJan 19, 2024
  8. Junio C HamanoJan 19, 2024
  9. 03/10 trailer: unify trailer formatting machineryLinus Arver via GitGitGadget, Jan 10, 2024
  10. Junio C HamanoJan 18, 2024
  11. Linus ArverJan 19, 2024
  12. 04/10 trailer: delete obsolete formatting functionsLinus Arver via GitGitGadget, Jan 10, 2024
  13. Junio C HamanoJan 19, 2024
  14. 05/10 sequencer: use the trailer iteratorLinus Arver via GitGitGadget, Jan 10, 2024
  15. Junio C HamanoJan 19, 2024
  16. Linus ArverJan 20, 2024
  17. Linus ArverJan 22, 2024
  18. 06/10 trailer: make trailer_info struct privateLinus Arver via GitGitGadget, Jan 10, 2024
  19. Junio C HamanoJan 19, 2024
  20. Josh SteadmonJan 25, 2024
  21. Junio C HamanoJan 25, 2024
  22. 07/10 trailer: spread usage of "trailer_block" languageLinus Arver via GitGitGadget, Jan 10, 2024
  23. Junio C HamanoJan 19, 2024
  24. Linus ArverJan 20, 2024
  25. 08/10 trailer: prepare to move parse_trailers_from_command_line_args() to builtinLinus Arver via GitGitGadget, Jan 10, 2024
  26. Josh SteadmonJan 25, 2024
  27. Linus ArverJan 26, 2024
  28. 09/10 trailer: move arg handling to interpret-trailers.cLinus Arver via GitGitGadget, Jan 10, 2024
  29. Junio C HamanoJan 19, 2024
  30. Linus ArverJan 20, 2024
  31. 10/10 trailer: delete obsolete argument handling code from APILinus Arver via GitGitGadget, Jan 10, 2024
  32. Junio C HamanoJan 10, 2024
  33. Linus ArverJan 13, 2024
  34. Linus ArverJan 14, 2024
  35. Josh SteadmonJan 25, 2024
  36. 00/10 Enrich Trailer APILinus Arver via GitGitGadget, Jan 26, 2024
  37. 01/10 trailer: prepare to expose functions as part of APILinus Arver via GitGitGadget, Jan 26, 2024
  38. Josh SteadmonJan 30, 2024
  39. Linus ArverJan 30, 2024
  40. 02/10 trailer: move interpret_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Jan 26, 2024
  41. 03/10 trailer: unify trailer formatting machineryLinus Arver via GitGitGadget, Jan 26, 2024
  42. Josh SteadmonJan 30, 2024
  43. Linus ArverJan 30, 2024
  44. 04/10 trailer: delete obsolete formatting functionsLinus Arver via GitGitGadget, Jan 26, 2024
  45. 05/10 sequencer: use the trailer iteratorLinus Arver via GitGitGadget, Jan 26, 2024
  46. 06/10 trailer: make trailer_info struct privateLinus Arver via GitGitGadget, Jan 26, 2024
  47. 07/10 trailer: spread usage of "trailer_block" languageLinus Arver via GitGitGadget, Jan 26, 2024
  48. 08/10 trailer: prepare to move parse_trailers_from_command_line_args() to builtinLinus Arver via GitGitGadget, Jan 26, 2024
  49. 09/10 trailer: move arg handling to interpret-trailers.cLinus Arver via GitGitGadget, Jan 26, 2024
  50. Linus ArverJan 28, 2024
  51. Linus ArverJan 28, 2024
  52. 10/10 trailer: delete obsolete argument handling code from APILinus Arver via GitGitGadget, Jan 26, 2024
  53. 00/10 Enrich Trailer APILinus Arver via GitGitGadget, Jan 31, 2024
  54. 01/10 trailer: prepare to expose functions as part of APILinus Arver via GitGitGadget, Jan 31, 2024
  55. 02/10 trailer: move interpret_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Jan 31, 2024
  56. Junio C HamanoJan 31, 2024
  57. Linus ArverJan 31, 2024
  58. 03/10 trailer: unify trailer formatting machineryLinus Arver via GitGitGadget, Jan 31, 2024
  59. Josh SteadmonJan 31, 2024
  60. Linus ArverJan 31, 2024
  61. Junio C HamanoFeb 1, 2024
  62. Linus ArverFeb 1, 2024
  63. Junio C HamanoJan 31, 2024
  64. Junio C HamanoJan 31, 2024
  65. Linus ArverFeb 1, 2024
  66. Junio C HamanoFeb 1, 2024
  67. Junio C HamanoFeb 1, 2024
  68. Linus ArverFeb 1, 2024
  69. Junio C HamanoFeb 1, 2024
  70. Linus ArverFeb 2, 2024
  71. Junio C HamanoFeb 2, 2024
  72. Linus ArverJan 31, 2024
  73. 04/10 sequencer: use the trailer iteratorLinus Arver via GitGitGadget, Jan 31, 2024
  74. Junio C HamanoFeb 1, 2024
  75. Linus ArverFeb 1, 2024
  76. Linus ArverFeb 3, 2024
  77. 05/10 trailer: make trailer_info struct privateLinus Arver via GitGitGadget, Jan 31, 2024
  78. Junio C HamanoFeb 1, 2024
  79. Linus ArverFeb 3, 2024
  80. Junio C HamanoFeb 3, 2024
  81. 06/10 trailer: spread usage of "trailer_block" languageLinus Arver via GitGitGadget, Jan 31, 2024
  82. Junio C HamanoFeb 1, 2024
  83. Linus ArverFeb 3, 2024
  84. 07/10 trailer: prepare to move parse_trailers_from_command_line_args() to builtinLinus Arver via GitGitGadget, Jan 31, 2024
  85. Junio C HamanoFeb 1, 2024
  86. 08/10 trailer: move arg handling to interpret-trailers.cLinus Arver via GitGitGadget, Jan 31, 2024
  87. Junio C HamanoFeb 1, 2024
  88. Linus ArverFeb 3, 2024
  89. Linus ArverFeb 6, 2024
  90. 09/10 trailer: delete obsolete argument handling code from APILinus Arver via GitGitGadget, Jan 31, 2024
  91. Junio C HamanoFeb 1, 2024
  92. Linus ArverFeb 3, 2024
  93. 10/10 trailer: introduce "template" term for readabilityLinus Arver via GitGitGadget, Jan 31, 2024
  94. 00/28 Enrich Trailer APILinus Arver via GitGitGadget, Feb 6, 2024
  95. 01/28 trailer: free trailer_info _after_ all related usageLinus Arver via GitGitGadget, Feb 6, 2024
  96. 02/28 shortlog: add test for de-duplicating folded trailersLinus Arver via GitGitGadget, Feb 6, 2024
  97. 03/28 trailer: prepare to expose functions as part of APILinus Arver via GitGitGadget, Feb 6, 2024
  98. 04/28 trailer: move interpret_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Feb 6, 2024
  99. 05/28 trailer: start preparing for formatting unificationLinus Arver via GitGitGadget, Feb 6, 2024
  100. 06/28 trailer_info_get(): reorder parametersLinus Arver via GitGitGadget, Feb 6, 2024
  101. 07/28 format_trailers(): use strbuf instead of FILELinus Arver via GitGitGadget, Feb 6, 2024
  102. 08/28 format_trailer_info(): move "fast path" to callerLinus Arver via GitGitGadget, Feb 6, 2024
  103. 09/28 format_trailers_from_commit(): indirectly call trailer_info_get()Linus Arver via GitGitGadget, Feb 6, 2024
  104. 10/28 format_trailer_info(): use trailer_item objectsLinus Arver via GitGitGadget, Feb 6, 2024
  105. Junio C HamanoFeb 9, 2024
  106. Linus ArverFeb 13, 2024
  107. 11/28 format_trailer_info(): drop redundant unfold_value()Linus Arver via GitGitGadget, Feb 6, 2024
  108. Junio C HamanoFeb 9, 2024
  109. 12/28 format_trailer_info(): append newline for non-trailer linesLinus Arver via GitGitGadget, Feb 6, 2024
  110. Junio C HamanoFeb 9, 2024
  111. Christian CouderFeb 12, 2024
  112. Linus ArverFeb 13, 2024
  113. 13/28 trailer: begin formatting unificationLinus Arver via GitGitGadget, Feb 6, 2024
  114. 14/28 format_trailer_info(): teach it about opts->trim_emptyLinus Arver via GitGitGadget, Feb 6, 2024
  115. Christian CouderFeb 12, 2024
  116. Linus ArverFeb 13, 2024
  117. Christian CouderFeb 13, 2024
  118. 15/28 format_trailer_info(): avoid double-printing the separatorLinus Arver via GitGitGadget, Feb 6, 2024
  119. Christian CouderFeb 12, 2024
  120. Linus ArverFeb 13, 2024
  121. Christian CouderFeb 13, 2024
  122. Linus ArverFeb 13, 2024
  123. Linus ArverMar 15, 2024
  124. Kristoffer HaugsbakkFeb 13, 2024
  125. 16/28 trailer: finish formatting unificationLinus Arver via GitGitGadget, Feb 6, 2024
  126. Junio C HamanoFeb 9, 2024
  127. Christian CouderFeb 12, 2024
  128. Linus ArverFeb 13, 2024
  129. 17/28 trailer: teach iterator about non-trailer linesLinus Arver via GitGitGadget, Feb 6, 2024
  130. 18/28 sequencer: use the trailer iteratorLinus Arver via GitGitGadget, Feb 6, 2024
  131. 19/28 trailer: make trailer_info struct privateLinus Arver via GitGitGadget, Feb 6, 2024
  132. Junio C HamanoFeb 9, 2024
  133. Linus ArverFeb 13, 2024
  134. Christian CouderFeb 12, 2024
  135. Linus ArverFeb 13, 2024
  136. 20/28 trailer: retire trailer_info_get() from APILinus Arver via GitGitGadget, Feb 6, 2024
  137. 21/28 trailer: spread usage of "trailer_block" languageLinus Arver via GitGitGadget, Feb 6, 2024
  138. Christian CouderFeb 12, 2024
  139. Linus ArverFeb 13, 2024
  140. 22/28 trailer: prepare to delete "parse_trailers_from_command_line_args()"Linus Arver via GitGitGadget, Feb 6, 2024
  141. Christian CouderFeb 12, 2024
  142. Linus ArverFeb 13, 2024
  143. 23/28 trailer: add new helper functions to APILinus Arver via GitGitGadget, Feb 6, 2024
  144. Christian CouderFeb 12, 2024
  145. Linus ArverFeb 13, 2024
  146. 24/28 trailer_add_arg_item(): drop new_trailer_item usageLinus Arver via GitGitGadget, Feb 6, 2024
  147. 25/28 trailer: deprecate "new_trailer_item" struct from APILinus Arver via GitGitGadget, Feb 6, 2024
  148. 26/28 trailer: unify "--trailer ..." arg handlingLinus Arver via GitGitGadget, Feb 6, 2024
  149. Christian CouderFeb 12, 2024
  150. Linus ArverFeb 13, 2024
  151. 27/28 trailer_set_*(): put out parameter at the endLinus Arver via GitGitGadget, Feb 6, 2024
  152. Christian CouderFeb 12, 2024
  153. Linus ArverFeb 13, 2024
  154. 28/28 trailer: introduce "template" term for readabilityLinus Arver via GitGitGadget, Feb 6, 2024
  155. Christian CouderFeb 12, 2024
  156. Linus ArverFeb 13, 2024
  157. Christian CouderFeb 12, 2024
  158. Junio C HamanoFeb 13, 2024
  159. Christian CouderFeb 13, 2024
  160. Junio C HamanoFeb 13, 2024
  161. Christian CouderFeb 13, 2024
  162. Linus ArverFeb 16, 2024
  163. Linus ArverFeb 13, 2024
  164. Junio C HamanoFeb 13, 2024
  165. Kristoffer HaugsbakkFeb 13, 2024
  166. Christian CouderFeb 13, 2024
  167. Linus ArverFeb 16, 2024
  168. 0/9 Enrich Trailer APILinus Arver via GitGitGadget, Feb 16, 2024
  169. 1/9 trailer: free trailer_info _after_ all related usageLinus Arver via GitGitGadget, Feb 16, 2024
  170. 2/9 shortlog: add test for de-duplicating folded trailersLinus Arver via GitGitGadget, Feb 16, 2024
  171. 3/9 trailer: prepare to expose functions as part of APILinus Arver via GitGitGadget, Feb 16, 2024
  172. Christian CouderFeb 19, 2024
  173. Linus ArverFeb 29, 2024
  174. Junio C HamanoFeb 29, 2024
  175. Linus ArverFeb 29, 2024
  176. 4/9 trailer: move interpret_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Feb 16, 2024
  177. 5/9 trailer: start preparing for formatting unificationLinus Arver via GitGitGadget, Feb 16, 2024
  178. Christian CouderFeb 19, 2024
  179. Linus ArverFeb 29, 2024
  180. 6/9 trailer_info_get(): reorder parametersLinus Arver via GitGitGadget, Feb 16, 2024
  181. 7/9 format_trailers(): use strbuf instead of FILELinus Arver via GitGitGadget, Feb 16, 2024
  182. 8/9 format_trailer_info(): move "fast path" to callerLinus Arver via GitGitGadget, Feb 16, 2024
  183. 9/9 format_trailers_from_commit(): indirectly call trailer_info_get()Linus Arver via GitGitGadget, Feb 16, 2024
  184. Christian CouderFeb 19, 2024
  185. Linus ArverFeb 29, 2024
  186. Christian CouderFeb 19, 2024
  187. 0/9 Enrich Trailer APILinus Arver via GitGitGadget, Mar 1, 2024
  188. 1/9 trailer: free trailer_info _after_ all related usageLinus Arver via GitGitGadget, Mar 1, 2024
  189. 2/9 shortlog: add test for de-duplicating folded trailersLinus Arver via GitGitGadget, Mar 1, 2024
  190. 3/9 trailer: rename functions to use 'trailer'Linus Arver via GitGitGadget, Mar 1, 2024
  191. 4/9 trailer: move interpret_trailers() to interpret-trailers.cLinus Arver via GitGitGadget, Mar 1, 2024
  192. 5/9 trailer: reorder format_trailers_from_commit() parametersLinus Arver via GitGitGadget, Mar 1, 2024
  193. 6/9 trailer_info_get(): reorder parametersLinus Arver via GitGitGadget, Mar 1, 2024
  194. 7/9 format_trailers(): use strbuf instead of FILELinus Arver via GitGitGadget, Mar 1, 2024
  195. 8/9 format_trailer_info(): move "fast path" to callerLinus Arver via GitGitGadget, Mar 1, 2024
  196. 9/9 format_trailers_from_commit(): indirectly call trailer_info_get()Linus Arver via GitGitGadget, Mar 1, 2024
  197. Junio C HamanoMar 5, 2024
  198. Josh SteadmonMar 5, 2024
  199. Junio C HamanoMar 5, 2024
  200. Christian CouderMar 6, 2024
  201. Junio C HamanoMar 6, 2024
  202. Junio C HamanoMar 6, 2024

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.