trailer: libify a couple of functions
Move create_in_place_tempfile() and process_trailers() from builtin/interpret-trailers.c into trailer.c and expose it via trailer.h. This reverts most of ae0ec2e0e0b (trailer: move interpret_trailers() to interpret-trailers.c, 2024-03-01) and lets other call sites reuse the same trailer rewriting logic. Signed-off-by: Li Chen <me@linux.beauty> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Li Chen committed
Mar 6, 2026 at 14:53 UTC
a4fd4c523444f6b7d11b7af4dc6d790ac4fd8ec5
3 files changed
+87
-70
builtin/interpret-trailers.c
+1
-70
@@ -93,39 +93,6 @@ static int parse_opt_parse(const struct option *opt, const char *arg,
93
return 0;
94
}
95
96
-
97
-static struct tempfile *create_in_place_tempfile(const char *file)
98
-{
99
- struct tempfile *tempfile = NULL;
100
- struct stat st;
101
- struct strbuf filename_template = STRBUF_INIT;
102
- const char *tail;
103
-
104
- if (stat(file, &st)) {
105
- error_errno(_("could not stat %s"), file);
106
- return NULL;
107
- }
108
- if (!S_ISREG(st.st_mode)) {
109
- error(_("file %s is not a regular file"), file);
110
- return NULL;
111
- }
112
- if (!(st.st_mode & S_IWUSR)) {
113
- error(_("file %s is not writable by user"), file);
114
- return NULL;
115
- }
116
- /* Create temporary file in the same directory as the original */
117
- tail = find_last_dir_sep(file);
118
- if (tail)
119
- strbuf_add(&filename_template, file, tail - file + 1);
120
- strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
121
-
122
- tempfile = mks_tempfile_m(filename_template.buf, st.st_mode);
123
-
124
- strbuf_release(&filename_template);
125
-
126
- return tempfile;
127
-}
128
-
96
static void read_input_file(struct strbuf *sb, const char *file)
97
{
98
if (file) {
@@ -138,42 +105,6 @@ static void read_input_file(struct strbuf *sb, const char *file)
105
strbuf_complete_line(sb);
106
}
107
141
-static void process_trailers(const struct process_trailer_options *opts,
142
- struct list_head *new_trailer_head,
143
- struct strbuf *input, struct strbuf *out)
144
-{
145
- LIST_HEAD(head);
146
- struct trailer_block *trailer_block;
147
-
148
- trailer_block = parse_trailers(opts, input->buf, &head);
149
-
150
- /* Print the lines before the trailer block */
151
- if (!opts->only_trailers)
152
- strbuf_add(out, input->buf, trailer_block_start(trailer_block));
153
-
154
- if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block))
155
- strbuf_addch(out, '\n');
156
-
157
- if (!opts->only_input) {
158
- LIST_HEAD(config_head);
159
- LIST_HEAD(arg_head);
160
- parse_trailers_from_config(&config_head);
161
- parse_trailers_from_command_line_args(&arg_head, new_trailer_head);
162
- list_splice(&config_head, &arg_head);
163
- process_trailers_lists(&head, &arg_head);
164
- }
165
-
166
- /* Print trailer block. */
167
- format_trailers(opts, &head, out);
168
- free_trailers(&head);
169
-
170
- /* Print the lines after the trailer block as is. */
171
- if (!opts->only_trailers)
172
- strbuf_add(out, input->buf + trailer_block_end(trailer_block),
173
- input->len - trailer_block_end(trailer_block));
174
- trailer_block_release(trailer_block);
175
-}
176
-
108
static void interpret_trailers(const struct process_trailer_options *opts,
109
struct list_head *new_trailer_head,
110
const char *file)
@@ -188,7 +119,7 @@ static void interpret_trailers(const struct process_trailer_options *opts,
119
read_input_file(&input, file);
120
121
if (opts->in_place) {
191
- tempfile = create_in_place_tempfile(file);
122
+ tempfile = trailer_create_in_place_tempfile(file);
123
if (!tempfile)
124
die(NULL);
125
fd = tempfile->fd;
trailer.c
+70
@@ -9,6 +9,8 @@
9
#include "commit.h"
10
#include "trailer.h"
11
#include "list.h"
12
+#include "tempfile.h"
13
+
14
/*
15
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
16
*/
@@ -1224,6 +1226,38 @@ void trailer_iterator_release(struct trailer_iterator *iter)
1226
strbuf_release(&iter->key);
1227
}
1228
1229
+struct tempfile *trailer_create_in_place_tempfile(const char *file)
1230
+{
1231
+ struct tempfile *tempfile = NULL;
1232
+ struct stat st;
1233
+ struct strbuf filename_template = STRBUF_INIT;
1234
+ const char *tail;
1235
+
1236
+ if (stat(file, &st)) {
1237
+ error_errno(_("could not stat %s"), file);
1238
+ return NULL;
1239
+ }
1240
+ if (!S_ISREG(st.st_mode)) {
1241
+ error(_("file %s is not a regular file"), file);
1242
+ return NULL;
1243
+ }
1244
+ if (!(st.st_mode & S_IWUSR)) {
1245
+ error(_("file %s is not writable by user"), file);
1246
+ return NULL;
1247
+ }
1248
+ /* Create temporary file in the same directory as the original */
1249
+ tail = find_last_dir_sep(file);
1250
+ if (tail)
1251
+ strbuf_add(&filename_template, file, tail - file + 1);
1252
+ strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
1253
+
1254
+ tempfile = mks_tempfile_m(filename_template.buf, st.st_mode);
1255
+
1256
+ strbuf_release(&filename_template);
1257
+
1258
+ return tempfile;
1259
+}
1260
+
1261
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
1262
{
1263
struct child_process run_trailer = CHILD_PROCESS_INIT;
@@ -1235,3 +1269,39 @@ int amend_file_with_trailers(const char *path, const struct strvec *trailer_args
1269
strvec_pushv(&run_trailer.args, trailer_args->v);
1270
return run_command(&run_trailer);
1271
}
1272
+
1273
+void process_trailers(const struct process_trailer_options *opts,
1274
+ struct list_head *new_trailer_head,
1275
+ struct strbuf *input, struct strbuf *out)
1276
+{
1277
+ LIST_HEAD(head);
1278
+ struct trailer_block *trailer_block;
1279
+
1280
+ trailer_block = parse_trailers(opts, input->buf, &head);
1281
+
1282
+ /* Print the lines before the trailer block */
1283
+ if (!opts->only_trailers)
1284
+ strbuf_add(out, input->buf, trailer_block_start(trailer_block));
1285
+
1286
+ if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block))
1287
+ strbuf_addch(out, '\n');
1288
+
1289
+ if (!opts->only_input) {
1290
+ LIST_HEAD(config_head);
1291
+ LIST_HEAD(arg_head);
1292
+ parse_trailers_from_config(&config_head);
1293
+ parse_trailers_from_command_line_args(&arg_head, new_trailer_head);
1294
+ list_splice(&config_head, &arg_head);
1295
+ process_trailers_lists(&head, &arg_head);
1296
+ }
1297
+
1298
+ /* Print trailer block. */
1299
+ format_trailers(opts, &head, out);
1300
+ free_trailers(&head);
1301
+
1302
+ /* Print the lines after the trailer block as is. */
1303
+ if (!opts->only_trailers)
1304
+ strbuf_add(out, input->buf + trailer_block_end(trailer_block),
1305
+ input->len - trailer_block_end(trailer_block));
1306
+ trailer_block_release(trailer_block);
1307
+}
trailer.h
+16
@@ -202,4 +202,20 @@ void trailer_iterator_release(struct trailer_iterator *iter);
202
*/
203
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args);
204
205
+/*
206
+ * Create a tempfile ""git-interpret-trailers-XXXXXX" in the same
207
+ * directory as file.
208
+ */
209
+struct tempfile *trailer_create_in_place_tempfile(const char *file);
210
+
211
+/*
212
+ * Rewrite the contents of input by processing its trailer block according to
213
+ * opts and (optionally) appending trailers from new_trailer_head.
214
+ *
215
+ * The rewritten message is appended to out (callers should strbuf_reset()
216
+ * first if needed).
217
+ */
218
+void process_trailers(const struct process_trailer_options *opts,
219
+ struct list_head *new_trailer_head,
220
+ struct strbuf *input, struct strbuf *out);
221
#endif /* TRAILER_H */