aboutsummaryrefslogtreecommitdiffstats
path: root/trailer.c
diff options
context:
space:
mode:
Diffstat (limited to 'trailer.c')
-rw-r--r--trailer.c129
1 files changed, 120 insertions, 9 deletions
diff --git a/trailer.c b/trailer.c
index 911a81ed99..f6ff2f01ee 100644
--- a/trailer.c
+++ b/trailer.c
@@ -7,8 +7,11 @@
#include "string-list.h"
#include "run-command.h"
#include "commit.h"
+#include "strvec.h"
#include "trailer.h"
#include "list.h"
+#include "wrapper.h"
+
/*
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
*/
@@ -772,6 +775,30 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head,
free(cl_separators);
}
+void validate_trailer_args_after_config(const struct strvec *cli_args)
+{
+ char *cl_separators;
+
+ trailer_config_init();
+
+ cl_separators = xstrfmt("=%s", separators);
+
+ for (size_t i = 0; i < cli_args->nr; i++) {
+ const char *txt = cli_args->v[i];
+ ssize_t separator_pos;
+
+ if (!*txt)
+ die(_("empty --trailer argument"));
+
+ separator_pos = find_separator(txt, cl_separators);
+ if (separator_pos == 0)
+ die(_("invalid trailer '%s': missing key before separator"),
+ txt);
+ }
+
+ free(cl_separators);
+}
+
static const char *next_line(const char *str)
{
const char *nl = strchrnul(str, '\n');
@@ -1224,14 +1251,98 @@ void trailer_iterator_release(struct trailer_iterator *iter)
strbuf_release(&iter->key);
}
-int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
+int amend_strbuf_with_trailers(struct strbuf *buf,
+ const struct strvec *trailer_args)
{
- struct child_process run_trailer = CHILD_PROCESS_INIT;
-
- run_trailer.git_cmd = 1;
- strvec_pushl(&run_trailer.args, "interpret-trailers",
- "--in-place", "--no-divider",
- path, NULL);
- strvec_pushv(&run_trailer.args, trailer_args->v);
- return run_command(&run_trailer);
+ struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
+ LIST_HEAD(new_trailer_head);
+ struct strbuf out = STRBUF_INIT;
+ size_t i;
+
+ opts.no_divider = 1;
+
+ for (i = 0; i < trailer_args->nr; i++) {
+ const char *text = trailer_args->v[i];
+ struct new_trailer_item *item;
+
+ if (!*text)
+ continue;
+ item = xcalloc(1, sizeof(*item));
+ INIT_LIST_HEAD(&item->list);
+ item->text = text;
+ list_add_tail(&item->list, &new_trailer_head);
+ }
+
+ process_trailers(&opts, &new_trailer_head, buf, &out);
+
+ strbuf_swap(buf, &out);
+ strbuf_release(&out);
+ while (!list_empty(&new_trailer_head)) {
+ struct new_trailer_item *item =
+ list_first_entry(&new_trailer_head, struct new_trailer_item, list);
+ list_del(&item->list);
+ free(item);
+ }
+ return 0;
+}
+
+int amend_file_with_trailers(const char *path,
+ const struct strvec *trailer_args)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ if (!trailer_args || !trailer_args->nr)
+ return 0;
+
+ if (strbuf_read_file(&buf, path, 0) < 0)
+ return error_errno("could not read '%s'", path);
+
+ if (amend_strbuf_with_trailers(&buf, trailer_args)) {
+ strbuf_release(&buf);
+ return error("failed to append trailers");
+ }
+
+ if (write_file_buf_gently(path, buf.buf, buf.len)) {
+ strbuf_release(&buf);
+ return -1;
+ }
+
+ strbuf_release(&buf);
+ return 0;
+ }
+
+void process_trailers(const struct process_trailer_options *opts,
+ struct list_head *new_trailer_head,
+ struct strbuf *sb, struct strbuf *out)
+{
+ LIST_HEAD(head);
+ struct trailer_block *trailer_block;
+
+ trailer_block = parse_trailers(opts, sb->buf, &head);
+
+ /* Print the lines before the trailer block */
+ if (!opts->only_trailers)
+ strbuf_add(out, sb->buf, trailer_block_start(trailer_block));
+
+ if (!opts->only_trailers && !blank_line_before_trailer_block(trailer_block))
+ strbuf_addch(out, '\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);
+ }
+
+ /* Print trailer block. */
+ format_trailers(opts, &head, out);
+ free_trailers(&head);
+
+ /* Print the lines after the trailer block as is. */
+ if (!opts->only_trailers)
+ strbuf_add(out, sb->buf + trailer_block_end(trailer_block),
+ sb->len - trailer_block_end(trailer_block));
+ trailer_block_release(trailer_block);
}