Skip to content

Commit 534a87d

Browse files
FirstLoveLifegitster
authored andcommitted
trailer: append trailers in-process and drop the fork to interpret-trailers
Route all trailer insertion through trailer_process() and make builtin/interpret-trailers just do file I/O before calling into it. amend_file_with_trailers() now shares the same code path. This removes the fork/exec and tempfile juggling, cutting overhead and simplifying error handling. No functional change. It also centralizes logic to prepare for follow-up rebase --trailer patch. Signed-off-by: Li Chen <chenl311@chinatelecom.cn> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 7aeb71a commit 534a87d

File tree

7 files changed

+90
-56
lines changed

7 files changed

+90
-56
lines changed

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ int cmd_commit(int argc,
17191719
OPT_STRING(0, "fixup", &fixup_message, N_("[(amend|reword):]commit"), N_("use autosquash formatted message to fixup or amend/reword specified commit")),
17201720
OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
17211721
OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
1722-
OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG),
1722+
OPT_CALLBACK_F(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, parse_opt_strvec),
17231723
OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
17241724
OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
17251725
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),

builtin/interpret-trailers.c

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "gettext.h"
1111
#include "parse-options.h"
1212
#include "string-list.h"
13-
#include "tempfile.h"
1413
#include "trailer.h"
1514
#include "config.h"
1615

@@ -93,37 +92,6 @@ static int parse_opt_parse(const struct option *opt, const char *arg,
9392
return 0;
9493
}
9594

96-
static struct tempfile *trailers_tempfile;
97-
98-
static FILE *create_in_place_tempfile(const char *file)
99-
{
100-
struct stat st;
101-
struct strbuf filename_template = STRBUF_INIT;
102-
const char *tail;
103-
FILE *outfile;
104-
105-
if (stat(file, &st))
106-
die_errno(_("could not stat %s"), file);
107-
if (!S_ISREG(st.st_mode))
108-
die(_("file %s is not a regular file"), file);
109-
if (!(st.st_mode & S_IWUSR))
110-
die(_("file %s is not writable by user"), file);
111-
112-
/* Create temporary file in the same directory as the original */
113-
tail = strrchr(file, '/');
114-
if (tail)
115-
strbuf_add(&filename_template, file, tail - file + 1);
116-
strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");
117-
118-
trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);
119-
strbuf_release(&filename_template);
120-
outfile = fdopen_tempfile(trailers_tempfile, "w");
121-
if (!outfile)
122-
die_errno(_("could not open temporary file"));
123-
124-
return outfile;
125-
}
126-
12795
static void read_input_file(struct strbuf *sb, const char *file)
12896
{
12997
if (file) {
@@ -142,21 +110,15 @@ static void interpret_trailers(const struct process_trailer_options *opts,
142110
{
143111
struct strbuf sb = STRBUF_INIT;
144112
struct strbuf out = STRBUF_INIT;
145-
FILE *outfile = stdout;
146-
147-
trailer_config_init();
148113

149114
read_input_file(&sb, file);
150115

151-
if (opts->in_place)
152-
outfile = create_in_place_tempfile(file);
153-
154116
process_trailers(opts, new_trailer_head, &sb, &out);
155117

156-
fwrite(out.buf, out.len, 1, outfile);
157118
if (opts->in_place)
158-
if (rename_tempfile(&trailers_tempfile, file))
159-
die_errno(_("could not rename temporary file to %s"), file);
119+
write_file_buf(file, out.buf, out.len);
120+
else
121+
strbuf_write(&out, stdout);
160122

161123
strbuf_release(&sb);
162124
strbuf_release(&out);
@@ -203,6 +165,8 @@ int cmd_interpret_trailers(int argc,
203165
git_interpret_trailers_usage,
204166
options);
205167

168+
trailer_config_init();
169+
206170
if (argc) {
207171
int i;
208172
for (i = 0; i < argc; i++)

builtin/tag.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,7 @@ int cmd_tag(int argc,
499499
OPT_CALLBACK_F('m', "message", &msg, N_("message"),
500500
N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg),
501501
OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
502-
OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"),
503-
N_("add custom trailer(s)"), PARSE_OPT_NONEG),
502+
OPT_CALLBACK_F(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, parse_opt_strvec),
504503
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
505504
OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
506505
OPT_CLEANUP(&cleanup_arg),

trailer.c

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "commit.h"
1010
#include "trailer.h"
1111
#include "list.h"
12+
#include "wrapper.h"
13+
1214
/*
1315
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
1416
*/
@@ -1224,18 +1226,66 @@ void trailer_iterator_release(struct trailer_iterator *iter)
12241226
strbuf_release(&iter->key);
12251227
}
12261228

1227-
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
1229+
static int amend_strbuf_with_trailers(struct strbuf *buf,
1230+
const struct strvec *trailer_args)
12281231
{
1229-
struct child_process run_trailer = CHILD_PROCESS_INIT;
1230-
1231-
run_trailer.git_cmd = 1;
1232-
strvec_pushl(&run_trailer.args, "interpret-trailers",
1233-
"--in-place", "--no-divider",
1234-
path, NULL);
1235-
strvec_pushv(&run_trailer.args, trailer_args->v);
1236-
return run_command(&run_trailer);
1232+
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1233+
LIST_HEAD(new_trailer_head);
1234+
struct strbuf out = STRBUF_INIT;
1235+
size_t i;
1236+
1237+
opts.no_divider = 1;
1238+
1239+
for (i = 0; i < trailer_args->nr; i++) {
1240+
const char *text = trailer_args->v[i];
1241+
struct new_trailer_item *item;
1242+
1243+
if (!*text)
1244+
continue;
1245+
item = xcalloc(1, sizeof(*item));
1246+
INIT_LIST_HEAD(&item->list);
1247+
item->text = text;
1248+
list_add_tail(&item->list, &new_trailer_head);
1249+
}
1250+
1251+
process_trailers(&opts, &new_trailer_head, buf, &out);
1252+
1253+
strbuf_swap(buf, &out);
1254+
strbuf_release(&out);
1255+
while (!list_empty(&new_trailer_head)) {
1256+
struct new_trailer_item *item =
1257+
list_first_entry(&new_trailer_head, struct new_trailer_item, list);
1258+
list_del(&item->list);
1259+
free(item);
1260+
}
1261+
return 0;
12371262
}
12381263

1264+
int amend_file_with_trailers(const char *path,
1265+
const struct strvec *trailer_args)
1266+
{
1267+
struct strbuf buf = STRBUF_INIT;
1268+
1269+
if (!trailer_args || !trailer_args->nr)
1270+
return 0;
1271+
1272+
if (strbuf_read_file(&buf, path, 0) < 0)
1273+
return error_errno("could not read '%s'", path);
1274+
1275+
if (amend_strbuf_with_trailers(&buf, trailer_args)) {
1276+
strbuf_release(&buf);
1277+
return error("failed to append trailers");
1278+
}
1279+
1280+
if (write_file_buf_gently(path, buf.buf, buf.len)) {
1281+
strbuf_release(&buf);
1282+
return -1;
1283+
}
1284+
1285+
strbuf_release(&buf);
1286+
return 0;
1287+
}
1288+
12391289
void process_trailers(const struct process_trailer_options *opts,
12401290
struct list_head *new_trailer_head,
12411291
struct strbuf *sb, struct strbuf *out)

trailer.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,8 @@ int trailer_iterator_advance(struct trailer_iterator *iter);
196196
void trailer_iterator_release(struct trailer_iterator *iter);
197197

198198
/*
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.
199+
* Augment a file to add trailers to it (similar to 'git interpret-trailers').
200+
* Returns 0 on success or a non-zero error code on failure.
202201
*/
203202
int amend_file_with_trailers(const char *path, const struct strvec *trailer_args);
204203

wrapper.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,22 @@ void write_file_buf(const char *path, const char *buf, size_t len)
688688
die_errno(_("could not close '%s'"), path);
689689
}
690690

691+
int write_file_buf_gently(const char *path, const char *buf, size_t len)
692+
{
693+
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
694+
695+
if (fd < 0)
696+
return error_errno(_("could not open '%s'"), path);
697+
if (write_in_full(fd, buf, len) < 0) {
698+
int ret = error_errno(_("could not write to '%s'"), path);
699+
close(fd);
700+
return ret;
701+
}
702+
if (close(fd))
703+
return error_errno(_("could not close '%s'"), path);
704+
return 0;
705+
}
706+
691707
void write_file(const char *path, const char *fmt, ...)
692708
{
693709
va_list params;

wrapper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ static inline ssize_t write_str_in_full(int fd, const char *str)
5656
*/
5757
void write_file_buf(const char *path, const char *buf, size_t len);
5858

59+
/**
60+
* Like write_file_buf(), but report errors instead of exiting. Returns 0 on
61+
* success or a negative value on error after emitting a message.
62+
*/
63+
int write_file_buf_gently(const char *path, const char *buf, size_t len);
64+
5965
/**
6066
* Like write_file_buf(), but format the contents into a buffer first.
6167
* Additionally, write_file() will append a newline if one is not already

0 commit comments

Comments
 (0)