trailer: move interpret_trailers() to interpret-trailers.c
The interpret-trailers.c builtin is the only place we need to call
interpret_trailers(), so move its definition there (together with a few
helper functions called only by it) and remove its external declaration
from <trailer.h>.
Several helper functions that are called by interpret_trailers() remain
in trailer.c because other callers in the same file still call them.
Declare them in <trailer.h> so that interpret_trailers() (now in
builtin/interpret-trailers.c) can continue calling them as a trailer API
user.
This enriches <trailer.h> with a more granular API, which can then be
unit-tested in the future (because interpret_trailers() by itself does
too many things to be able to be easily unit-tested).
Take this opportunity to demote some file-handling functions out of the
trailer API implementation, as these have nothing to do with trailers.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Linus Arver <linusa@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Linus Arver committedMar 1, 2024 at 00:14 UTCae0ec2e0e0bb26474f395504c6ed6fef3f59091f
3 files changed+123-109
builtin/interpret-trailers.c
+93
index 85a3413baf..d1cf0aa33a 100644--- a/builtin/interpret-trailers.c+++ b/builtin/interpret-trailers.c@@ -9,6 +9,7 @@ #include "gettext.h" #include "parse-options.h" #include "string-list.h"+#include "tempfile.h" #include "trailer.h" #include "config.h"@@ -91,6 +92,98 @@ static int parse_opt_parse(const struct option *opt, const char *arg, return 0; }+static struct tempfile *trailers_tempfile;++static FILE *create_in_place_tempfile(const char *file)+{+ struct stat st;+ struct strbuf filename_template = STRBUF_INIT;+ const char *tail;+ FILE *outfile;++ if (stat(file, &st))+ die_errno(_("could not stat %s"), file);+ if (!S_ISREG(st.st_mode))+ die(_("file %s is not a regular file"), file);+ if (!(st.st_mode & S_IWUSR))+ die(_("file %s is not writable by user"), file);++ /* Create temporary file in the same directory as the original */+ tail = strrchr(file, '/');+ if (tail)+ strbuf_add(&filename_template, file, tail - file + 1);+ strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");++ trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);+ strbuf_release(&filename_template);+ outfile = fdopen_tempfile(trailers_tempfile, "w");+ if (!outfile)+ die_errno(_("could not open temporary file"));++ return outfile;+}++static void read_input_file(struct strbuf *sb, const char *file)+{+ if (file) {+ if (strbuf_read_file(sb, file, 0) < 0)+ die_errno(_("could not read input file '%s'"), file);+ } else {+ if (strbuf_read(sb, fileno(stdin), 0) < 0)+ die_errno(_("could not read from stdin"));+ }+}++static void interpret_trailers(const struct process_trailer_options *opts,+ struct list_head *new_trailer_head,+ const char *file)+{+ LIST_HEAD(head);+ struct strbuf sb = STRBUF_INIT;+ struct trailer_info info;+ FILE *outfile = stdout;++ trailer_config_init();++ read_input_file(&sb, file);++ if (opts->in_place)+ outfile = create_in_place_tempfile(file);++ parse_trailers(opts, &info, sb.buf, &head);++ /* Print the lines before the trailers */+ if (!opts->only_trailers)+ fwrite(sb.buf, 1, info.trailer_block_start, outfile);++ if (!opts->only_trailers && !info.blank_line_before_trailer)+ fprintf(outfile, "\n");+++ if (!opts->only_input) {+ LIST_HEAD(config_head);+ LIST_HEAD(arg_head);+ parse_trailers_from_config(&config_head);+ parse_trailers_from_command_line_args(&arg_head, new_trailer_head);+ list_splice(&config_head, &arg_head);+ process_trailers_lists(&head, &arg_head);+ }++ format_trailers(opts, &head, outfile);+ free_trailers(&head);++ /* 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);++ if (opts->in_place)+ if (rename_tempfile(&trailers_tempfile, file))+ die_errno(_("could not rename temporary file to %s"), file);++ strbuf_release(&sb);+}+ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
trailer.c
+13-106
index 4a58005416..5025be9789 100644--- a/trailer.c+++ b/trailer.c@@ -5,7 +5,6 @@ #include "string-list.h" #include "run-command.h" #include "commit.h"-#include "tempfile.h" #include "trailer.h" #include "list.h" /*@@ -163,8 +162,8 @@ static void print_tok_val(FILE *outfile, const char *tok, const char *val) fprintf(outfile, "%s%c %s\n", tok, separators[0], val); }-static void format_trailers(const struct process_trailer_options *opts,- struct list_head *trailers, FILE *outfile)+void format_trailers(const struct process_trailer_options *opts,+ struct list_head *trailers, FILE *outfile) { struct list_head *pos; struct trailer_item *item;@@ -366,8 +365,8 @@ static int find_same_and_apply_arg(struct list_head *head, return 0; }-static void process_trailers_lists(struct list_head *head,- struct list_head *arg_head)+void process_trailers_lists(struct list_head *head,+ struct list_head *arg_head) { struct list_head *pos, *p; struct arg_item *arg_tok;@@ -589,7 +588,7 @@ static int git_trailer_config(const char *conf_key, const char *value, return 0; }-static void trailer_config_init(void)+void trailer_config_init(void) { if (configured) return;@@ -719,7 +718,7 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val, list_add_tail(&new_item->list, arg_head); }-static void parse_trailers_from_config(struct list_head *config_head)+void parse_trailers_from_config(struct list_head *config_head) { struct arg_item *item; struct list_head *pos;@@ -735,8 +734,8 @@ static void parse_trailers_from_config(struct list_head *config_head) } }-static void parse_trailers_from_command_line_args(struct list_head *arg_head,- struct list_head *new_trailer_head)+void parse_trailers_from_command_line_args(struct list_head *arg_head,+ struct list_head *new_trailer_head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT;@@ -775,17 +774,6 @@ static void parse_trailers_from_command_line_args(struct list_head *arg_head, free(cl_separators); }-static void read_input_file(struct strbuf *sb, const char *file)-{- if (file) {- if (strbuf_read_file(sb, file, 0) < 0)- die_errno(_("could not read input file '%s'"), file);- } else {- if (strbuf_read(sb, fileno(stdin), 0) < 0)- die_errno(_("could not read from stdin"));- }-}- static const char *next_line(const char *str) { const char *nl = strchrnul(str, '\n');@@ -1000,10 +988,10 @@ static void unfold_value(struct strbuf *val) * Parse trailers in "str", populating the trailer info and "head" * linked list structure. */-static void parse_trailers(struct trailer_info *info,- const char *str,- struct list_head *head,- const struct process_trailer_options *opts)+void parse_trailers(const struct process_trailer_options *opts,+ struct trailer_info *info,+ const char *str,+ struct list_head *head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT;@@ -1035,7 +1023,7 @@ static void parse_trailers(struct trailer_info *info, } }-static void free_trailers(struct list_head *trailers)+void free_trailers(struct list_head *trailers) { struct list_head *pos, *p; list_for_each_safe(pos, p, trailers) {@@ -1044,87 +1032,6 @@ static void free_trailers(struct list_head *trailers) } }-static struct tempfile *trailers_tempfile;--static FILE *create_in_place_tempfile(const char *file)-{- struct stat st;- struct strbuf filename_template = STRBUF_INIT;- const char *tail;- FILE *outfile;-- if (stat(file, &st))- die_errno(_("could not stat %s"), file);- if (!S_ISREG(st.st_mode))- die(_("file %s is not a regular file"), file);- if (!(st.st_mode & S_IWUSR))- die(_("file %s is not writable by user"), file);-- /* Create temporary file in the same directory as the original */- tail = strrchr(file, '/');- if (tail)- strbuf_add(&filename_template, file, tail - file + 1);- strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX");-- trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode);- strbuf_release(&filename_template);- outfile = fdopen_tempfile(trailers_tempfile, "w");- if (!outfile)- die_errno(_("could not open temporary file"));-- return outfile;-}--void interpret_trailers(const struct process_trailer_options *opts,- struct list_head *new_trailer_head,- const char *file)-{- LIST_HEAD(head);- struct strbuf sb = STRBUF_INIT;- struct trailer_info info;- FILE *outfile = stdout;-- trailer_config_init();-- read_input_file(&sb, file);-- if (opts->in_place)- outfile = create_in_place_tempfile(file);-- parse_trailers(&info, sb.buf, &head, opts);-- /* Print the lines before the trailers */- if (!opts->only_trailers)- fwrite(sb.buf, 1, info.trailer_block_start, outfile);-- if (!opts->only_trailers && !info.blank_line_before_trailer)- fprintf(outfile, "\n");--- if (!opts->only_input) {- LIST_HEAD(config_head);- LIST_HEAD(arg_head);- parse_trailers_from_config(&config_head);- parse_trailers_from_command_line_args(&arg_head, new_trailer_head);- list_splice(&config_head, &arg_head);- process_trailers_lists(&head, &arg_head);- }-- format_trailers(opts, &head, outfile);- free_trailers(&head);-- /* 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);-- if (opts->in_place)- if (rename_tempfile(&trailers_tempfile, file))- die_errno(_("could not rename temporary file to %s"), file);-- strbuf_release(&sb);-}- void trailer_info_get(struct trailer_info *info, const char *str, const struct process_trailer_options *opts) {