X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=trailer.c;h=3a0710a4583a4a11fa5a87cda88ef6a3d0610870;hb=07fa3836158f267184bb5cebaa1390364cdb8702;hp=f408f9b058dbbc33b1360cf36e1e023b7bba1a54;hpb=17ab51ee8ffcecc62813fe6c744cabb924f3fc9f;p=thirdparty%2Fgit.git diff --git a/trailer.c b/trailer.c index f408f9b058..3a0710a458 100644 --- a/trailer.c +++ b/trailer.c @@ -507,6 +507,8 @@ static int git_trailer_default_config(const char *conf_key, const char *value, warning(_("unknown value '%s' for key '%s'"), value, conf_key); } else if (!strcmp(trailer_item, "separators")) { + if (!value) + return config_error_nonbool(conf_key); separators = xstrdup(value); } } @@ -551,16 +553,22 @@ static int git_trailer_config(const char *conf_key, const char *value, case TRAILER_KEY: if (conf->key) warning(_("more than one %s"), conf_key); + if (!value) + return config_error_nonbool(conf_key); conf->key = xstrdup(value); break; case TRAILER_COMMAND: if (conf->command) warning(_("more than one %s"), conf_key); + if (!value) + return config_error_nonbool(conf_key); conf->command = xstrdup(value); break; case TRAILER_CMD: if (conf->cmd) warning(_("more than one %s"), conf_key); + if (!value) + return config_error_nonbool(conf_key); conf->cmd = xstrdup(value); break; case TRAILER_WHERE: @@ -711,30 +719,35 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val, list_add_tail(&new_item->list, arg_head); } -static void process_command_line_args(struct list_head *arg_head, - struct list_head *new_trailer_head) +static void parse_trailers_from_config(struct list_head *config_head) { struct arg_item *item; - struct strbuf tok = STRBUF_INIT; - struct strbuf val = STRBUF_INIT; - const struct conf_info *conf; struct list_head *pos; - /* - * In command-line arguments, '=' is accepted (in addition to the - * separators that are defined). - */ - char *cl_separators = xstrfmt("=%s", separators); - /* Add an arg item for each configured trailer with a command */ list_for_each(pos, &conf_head) { item = list_entry(pos, struct arg_item, list); if (item->conf.command) - add_arg_item(arg_head, + add_arg_item(config_head, xstrdup(token_from_item(item, NULL)), xstrdup(""), &item->conf, NULL); } +} + +static 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; + const struct conf_info *conf; + struct list_head *pos; + + /* + * In command-line arguments, '=' is accepted (in addition to the + * separators that are defined). + */ + char *cl_separators = xstrfmt("=%s", separators); /* Add an arg item for each trailer on the command line */ list_for_each(pos, new_trailer_head) { @@ -804,28 +817,56 @@ static ssize_t last_line(const char *buf, size_t len) } /* - * Return the position of the start of the patch or the length of str if there - * is no patch in the message. + * Find the end of the log message as an offset from the start of the input + * (where callers of this function are interested in looking for a trailers + * block in the same input). We have to consider two categories of content that + * can come at the end of the input which we want to ignore (because they don't + * belong in the log message): + * + * (1) the "patch part" which begins with a "---" divider and has patch + * information (like the output of git-format-patch), and + * + * (2) any trailing comment lines, blank lines like in the output of "git + * commit -v", or stuff below the "cut" (scissor) line. + * + * As a formula, the situation looks like this: + * + * INPUT = LOG MESSAGE + IGNORED + * + * where IGNORED can be either of the two categories described above. It may be + * that there is nothing to ignore. Now it may be the case that the LOG MESSAGE + * contains a trailer block, but that's not the concern of this function. */ -static size_t find_patch_start(const char *str) +static size_t find_end_of_log_message(const char *input, int no_divider) { + size_t end; const char *s; - for (s = str; *s; s = next_line(s)) { + /* Assume the naive end of the input is already what we want. */ + end = strlen(input); + + if (no_divider) + return end; + + /* Optionally skip over any patch part ("---" line and below). */ + for (s = input; *s; s = next_line(s)) { const char *v; - if (skip_prefix(s, "---", &v) && isspace(*v)) - return s - str; + if (skip_prefix(s, "---", &v) && isspace(*v)) { + end = s - input; + break; + } } - return s - str; + /* Skip over other ignorable bits. */ + return end - ignored_log_message_bytes(input, end); } /* * Return the position of the first trailer line or len if there are no * trailers. */ -static size_t find_trailer_start(const char *buf, size_t len) +static size_t find_trailer_block_start(const char *buf, size_t len) { const char *s; ssize_t end_of_title, l; @@ -920,12 +961,6 @@ continue_outer_loop: return len; } -/* Return the position of the end of the trailers. */ -static size_t find_trailer_end(const char *buf, size_t len) -{ - return len - ignore_non_trailer(buf, len); -} - static int ends_with_blank_line(const char *buf, size_t len) { ssize_t ll = last_line(buf, len); @@ -961,28 +996,24 @@ static void unfold_value(struct strbuf *val) strbuf_release(&out); } -static size_t process_input_file(FILE *outfile, - const char *str, - struct list_head *head, - const struct process_trailer_options *opts) +/* + * 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) { - struct trailer_info info; struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; size_t i; - trailer_info_get(&info, str, opts); - - /* Print lines before the trailers as is */ - if (!opts->only_trailers) - fwrite(str, 1, info.trailer_start - str, outfile); + trailer_info_get(info, str, opts); - if (!opts->only_trailers && !info.blank_line_before_trailer) - fprintf(outfile, "\n"); - - for (i = 0; i < info.trailer_nr; i++) { + for (i = 0; i < info->trailer_nr; i++) { int separator_pos; - char *trailer = info.trailers[i]; + char *trailer = info->trailers[i]; if (trailer[0] == comment_line_char) continue; separator_pos = find_separator(trailer, separators); @@ -1002,10 +1033,6 @@ static size_t process_input_file(FILE *outfile, strbuf_detach(&val, NULL)); } } - - trailer_info_release(&info); - - return info.trailer_end - str; } static void free_all(struct list_head *head) @@ -1054,7 +1081,7 @@ void process_trailers(const char *file, { LIST_HEAD(head); struct strbuf sb = STRBUF_INIT; - size_t trailer_end; + struct trailer_info info; FILE *outfile = stdout; ensure_configured(); @@ -1064,22 +1091,33 @@ void process_trailers(const char *file, if (opts->in_place) outfile = create_in_place_tempfile(file); + parse_trailers(&info, sb.buf, &head, opts); + /* Print the lines before the trailers */ - trailer_end = process_input_file(outfile, sb.buf, &head, opts); + 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); - process_command_line_args(&arg_head, new_trailer_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_all(outfile, &head, opts); free_all(&head); + trailer_info_release(&info); /* Print the lines after the trailers as is */ if (!opts->only_trailers) - fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile); + fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); if (opts->in_place) if (rename_tempfile(&trailers_tempfile, file)) @@ -1091,7 +1129,7 @@ void process_trailers(const char *file, void trailer_info_get(struct trailer_info *info, const char *str, const struct process_trailer_options *opts) { - int patch_start, trailer_end, trailer_start; + size_t end_of_log_message = 0, trailer_block_start = 0; struct strbuf **trailer_lines, **ptr; char **trailer_strings = NULL; size_t nr = 0, alloc = 0; @@ -1099,16 +1137,11 @@ void trailer_info_get(struct trailer_info *info, const char *str, ensure_configured(); - if (opts->no_divider) - patch_start = strlen(str); - else - patch_start = find_patch_start(str); - - trailer_end = find_trailer_end(str, patch_start); - trailer_start = find_trailer_start(str, trailer_end); + end_of_log_message = find_end_of_log_message(str, opts->no_divider); + trailer_block_start = find_trailer_block_start(str, end_of_log_message); - trailer_lines = strbuf_split_buf(str + trailer_start, - trailer_end - trailer_start, + trailer_lines = strbuf_split_buf(str + trailer_block_start, + end_of_log_message - trailer_block_start, '\n', 0); for (ptr = trailer_lines; *ptr; ptr++) { @@ -1129,9 +1162,9 @@ void trailer_info_get(struct trailer_info *info, const char *str, strbuf_list_free(trailer_lines); info->blank_line_before_trailer = ends_with_blank_line(str, - trailer_start); - info->trailer_start = str + trailer_start; - info->trailer_end = str + trailer_end; + trailer_block_start); + info->trailer_block_start = trailer_block_start; + info->trailer_block_end = end_of_log_message; info->trailers = trailer_strings; info->trailer_nr = nr; } @@ -1146,6 +1179,7 @@ void trailer_info_release(struct trailer_info *info) static void format_trailer_info(struct strbuf *out, const struct trailer_info *info, + const char *msg, const struct process_trailer_options *opts) { size_t origlen = out->len; @@ -1155,8 +1189,8 @@ static void format_trailer_info(struct strbuf *out, if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator && !opts->key_only && !opts->value_only && !opts->key_value_separator) { - strbuf_add(out, info->trailer_start, - info->trailer_end - info->trailer_start); + strbuf_add(out, msg + info->trailer_block_start, + info->trailer_block_end - info->trailer_block_start); return; } @@ -1210,7 +1244,7 @@ void format_trailers_from_commit(struct strbuf *out, const char *msg, struct trailer_info info; trailer_info_get(&info, msg, opts); - format_trailer_info(out, &info, opts); + format_trailer_info(out, &info, msg, opts); trailer_info_release(&info); } @@ -1220,14 +1254,14 @@ void trailer_iterator_init(struct trailer_iterator *iter, const char *msg) strbuf_init(&iter->key, 0); strbuf_init(&iter->val, 0); opts.no_divider = 1; - trailer_info_get(&iter->info, msg, &opts); - iter->cur = 0; + trailer_info_get(&iter->internal.info, msg, &opts); + iter->internal.cur = 0; } int trailer_iterator_advance(struct trailer_iterator *iter) { - while (iter->cur < iter->info.trailer_nr) { - char *trailer = iter->info.trailers[iter->cur++]; + while (iter->internal.cur < iter->internal.info.trailer_nr) { + char *trailer = iter->internal.info.trailers[iter->internal.cur++]; int separator_pos = find_separator(trailer, separators); if (separator_pos < 1) @@ -1245,7 +1279,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) void trailer_iterator_release(struct trailer_iterator *iter) { - trailer_info_release(&iter->info); + trailer_info_release(&iter->internal.info); strbuf_release(&iter->val); strbuf_release(&iter->key); }