Skip to content

Commit 6b2243f

Browse files
FirstLoveLifegitster
authored andcommitted
trailer: append trailers without fork/exec
Introduce amend_strbuf_with_trailers() to apply trailer additions to a message buffer via process_trailers(), avoiding the need to run git interpret-trailers as a child process. Update amend_file_with_trailers() to use the in-process helper and rewrite the target file via tempfile+rename, preserving the previous in-place semantics. As the trailers are no longer added in a separate process and trailer_config_init() die()s on missing config values it is called early on in cmd_commit() and cmd_tag() so that they die() early before writing the message file. The trailer arguments are now also sanity checked. Keep existing callers unchanged by continuing to accept argv-style --trailer=<trailer> entries and stripping the prefix before feeding the in-process implementation. 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>
1 parent a4fd4c5 commit 6b2243f

4 files changed

Lines changed: 147 additions & 12 deletions

File tree

builtin/commit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,9 @@ int cmd_commit(int argc,
18201820
argc = parse_and_validate_options(argc, argv, builtin_commit_options,
18211821
builtin_commit_usage,
18221822
prefix, current_head, &s);
1823+
if (trailer_args.nr)
1824+
trailer_config_init();
1825+
18231826
if (verbose == -1)
18241827
verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
18251828

builtin/tag.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,9 @@ int cmd_tag(int argc,
568568
if (cmdmode == 'l')
569569
setup_auto_pager("tag", 1);
570570

571+
if (trailer_args.nr)
572+
trailer_config_init();
573+
571574
if (opt.sign == -1)
572575
opt.sign = cmdmode ? 0 : config_sign_tag > 0;
573576

trailer.c

Lines changed: 124 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "string-list.h"
88
#include "run-command.h"
99
#include "commit.h"
10+
#include "strvec.h"
1011
#include "trailer.h"
1112
#include "list.h"
1213
#include "tempfile.h"
@@ -774,6 +775,35 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head,
774775
free(cl_separators);
775776
}
776777

778+
int validate_trailer_args(const struct strvec *cli_args)
779+
{
780+
char *cl_separators;
781+
int ret = 0;
782+
783+
trailer_config_init();
784+
785+
cl_separators = xstrfmt("=%s", separators);
786+
787+
for (size_t i = 0; i < cli_args->nr; i++) {
788+
const char *txt = cli_args->v[i];
789+
ssize_t separator_pos;
790+
791+
if (!*txt) {
792+
ret = error(_("empty --trailer argument"));
793+
goto out;
794+
}
795+
separator_pos = find_separator(txt, cl_separators);
796+
if (separator_pos == 0) {
797+
ret = error(_("invalid trailer '%s': missing key before separator"),
798+
txt);
799+
goto out;
800+
}
801+
}
802+
out:
803+
free(cl_separators);
804+
return ret;
805+
}
806+
777807
static const char *next_line(const char *str)
778808
{
779809
const char *nl = strchrnul(str, '\n');
@@ -1258,16 +1288,101 @@ struct tempfile *trailer_create_in_place_tempfile(const char *file)
12581288
return tempfile;
12591289
}
12601290

1261-
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
1291+
int amend_strbuf_with_trailers(struct strbuf *buf,
1292+
const struct strvec *trailer_args)
12621293
{
1263-
struct child_process run_trailer = CHILD_PROCESS_INIT;
1264-
1265-
run_trailer.git_cmd = 1;
1266-
strvec_pushl(&run_trailer.args, "interpret-trailers",
1267-
"--in-place", "--no-divider",
1268-
path, NULL);
1269-
strvec_pushv(&run_trailer.args, trailer_args->v);
1270-
return run_command(&run_trailer);
1294+
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1295+
LIST_HEAD(new_trailer_head);
1296+
struct strbuf out = STRBUF_INIT;
1297+
size_t i;
1298+
int ret = 0;
1299+
1300+
opts.no_divider = 1;
1301+
1302+
for (i = 0; i < trailer_args->nr; i++) {
1303+
const char *text = trailer_args->v[i];
1304+
struct new_trailer_item *item;
1305+
1306+
if (!*text) {
1307+
ret = error(_("empty --trailer argument"));
1308+
goto out;
1309+
}
1310+
item = xcalloc(1, sizeof(*item));
1311+
item->text = xstrdup(text);
1312+
list_add_tail(&item->list, &new_trailer_head);
1313+
}
1314+
1315+
process_trailers(&opts, &new_trailer_head, buf, &out);
1316+
1317+
strbuf_swap(buf, &out);
1318+
out:
1319+
strbuf_release(&out);
1320+
free_trailers(&new_trailer_head);
1321+
1322+
return ret;
1323+
}
1324+
1325+
static int write_file_in_place(const char *path, const struct strbuf *buf)
1326+
{
1327+
struct tempfile *tempfile = trailer_create_in_place_tempfile(path);
1328+
if (!tempfile)
1329+
return -1;
1330+
1331+
if (write_in_full(tempfile->fd, buf->buf, buf->len) < 0)
1332+
return error_errno(_("could not write to temporary file"));
1333+
1334+
if (rename_tempfile(&tempfile, path))
1335+
return error_errno(_("could not rename temporary file to %s"), path);
1336+
1337+
return 0;
1338+
}
1339+
1340+
int amend_file_with_trailers(const char *path,
1341+
const struct strvec *trailer_args)
1342+
{
1343+
struct strbuf buf = STRBUF_INIT;
1344+
struct strvec stripped_trailer_args = STRVEC_INIT;
1345+
int ret = 0;
1346+
size_t i;
1347+
1348+
if (!trailer_args)
1349+
BUG("amend_file_with_trailers called with NULL trailer_args");
1350+
if (!trailer_args->nr)
1351+
return 0;
1352+
1353+
for (i = 0; i < trailer_args->nr; i++) {
1354+
const char *txt = trailer_args->v[i];
1355+
1356+
/*
1357+
* Historically amend_file_with_trailers() passed its arguments
1358+
* to "git interpret-trailers", which expected argv entries in
1359+
* "--trailer=<trailer>" form. Continue to accept those for
1360+
* existing callers, but pass only the value portion to the
1361+
* in-process implementation.
1362+
*/
1363+
skip_prefix(txt, "--trailer=", &txt);
1364+
if (!*txt) {
1365+
ret = error(_("empty --trailer argument"));
1366+
goto out;
1367+
}
1368+
strvec_push(&stripped_trailer_args, txt);
1369+
}
1370+
1371+
if (validate_trailer_args(&stripped_trailer_args)) {
1372+
ret = -1;
1373+
goto out;
1374+
}
1375+
if (strbuf_read_file(&buf, path, 0) < 0)
1376+
ret = error_errno(_("could not read '%s'"), path);
1377+
else
1378+
amend_strbuf_with_trailers(&buf, &stripped_trailer_args);
1379+
1380+
if (!ret)
1381+
ret = write_file_in_place(path, &buf);
1382+
out:
1383+
strvec_clear(&stripped_trailer_args);
1384+
strbuf_release(&buf);
1385+
return ret;
12711386
}
12721387

12731388
void process_trailers(const struct process_trailer_options *opts,

trailer.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ void parse_trailers_from_config(struct list_head *config_head);
6868
void parse_trailers_from_command_line_args(struct list_head *arg_head,
6969
struct list_head *new_trailer_head);
7070

71+
int validate_trailer_args(const struct strvec *cli_args);
72+
7173
void process_trailers_lists(struct list_head *head,
7274
struct list_head *arg_head);
7375

@@ -196,9 +198,21 @@ int trailer_iterator_advance(struct trailer_iterator *iter);
196198
void trailer_iterator_release(struct trailer_iterator *iter);
197199

198200
/*
199-
* Augment a file to add trailers to it by running git-interpret-trailers.
200-
* This calls run_command() and its return value is the same (i.e. 0 for
201-
* success, various non-zero for other errors). See run-command.h.
201+
* Append trailers specified in trailer_args to buf in-place.
202+
*
203+
* Each element of trailer_args should be in the same format as the value
204+
* accepted by --trailer=<trailer> (i.e., without the --trailer= prefix).
205+
*/
206+
int amend_strbuf_with_trailers(struct strbuf *buf,
207+
const struct strvec *trailer_args);
208+
209+
/*
210+
* Augment a file by appending trailers specified in trailer_args.
211+
*
212+
* Each element of trailer_args should be an argv-style --trailer=<trailer>
213+
* option (i.e., including the --trailer= prefix).
214+
*
215+
* Returns 0 on success or a non-zero error code on failure.
202216
*/
203217
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args);
204218

0 commit comments

Comments
 (0)