interpret-trailers: refactor create_in_place_tempfile()

Refactor create_in_place_tempfile() in preparation for moving it to tralier.c. Change the return type to return a `struct tempfile*` instead of a `FILE*` so that we can remove the file scope tempfile variable. Since 076aa2cbda5 (tempfile: auto-allocate tempfiles on heap, 2017-09-05) it has not been necessary to make tempfile varibales static so this is safe. Also use error() and return NULL in place of die() so the caller can exit gracefully and use find_last_dir_sep() rather than strchr() to find the parent directory. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Mar 6, 2026 at 14:53 UTC 876b2ebee2cd520f6ce78ac9bcf4c5486e509a1d
1 file changed +29 -22
builtin/interpret-trailers.c
+29 -22
@@ -93,35 +93,37 @@ static int parse_opt_parse(const struct option *opt, const char *arg,
93 return 0;
94 }
95
96 -static struct tempfile *trailers_tempfile;
96
98 -static FILE *create_in_place_tempfile(const char *file)
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 - 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);
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 */
113 - tail = strrchr(file, '/');
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
118 - trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);
122 + tempfile = mks_tempfile_m(filename_template.buf, st.st_mode);
123 +
124 strbuf_release(&filename_template);
120 - outfile = fdopen_tempfile(trailers_tempfile, "w");
121 - if (!outfile)
122 - die_errno(_("could not open temporary file"));
125
124 - return outfile;
126 + return tempfile;
127 }
128
129 static void read_input_file(struct strbuf *sb, const char *file)
@@ -178,20 +180,25 @@ static void interpret_trailers(const struct process_trailer_options *opts,
180 {
181 struct strbuf input = STRBUF_INIT;
182 struct strbuf out = STRBUF_INIT;
181 - FILE *outfile = stdout;
183 + struct tempfile *tempfile = NULL;
184 + int fd = 1;
185
186 trailer_config_init();
187
188 read_input_file(&input, file);
189
187 - if (opts->in_place)
188 - outfile = create_in_place_tempfile(file);
189 -
190 + if (opts->in_place) {
191 + tempfile = create_in_place_tempfile(file);
192 + if (!tempfile)
193 + die(NULL);
194 + fd = tempfile->fd;
195 + }
196 process_trailers(opts, new_trailer_head, &input, &out);
197
192 - strbuf_write(&out, outfile);
198 + if (write_in_full(fd, out.buf, out.len) < 0)
199 + die_errno(_("could not write to temporary file '%s'"), file);
200 if (opts->in_place)
194 - if (rename_tempfile(&trailers_tempfile, file))
201 + if (rename_tempfile(&tempfile, file))
202 die_errno(_("could not rename temporary file to %s"), file);
203
204 strbuf_release(&input);