diff options
Diffstat (limited to 'pretty.c')
-rw-r--r-- | pretty.c | 121 |
1 files changed, 71 insertions, 50 deletions
@@ -783,6 +783,7 @@ enum trunc_type { }; struct format_commit_context { + struct repository *repository; const struct commit *commit; const struct pretty_print_context *pretty_ctx; unsigned commit_header_parsed:1; @@ -1148,6 +1149,63 @@ static int format_trailer_match_cb(const struct strbuf *key, void *ud) return 0; } +int format_set_trailers_options(struct process_trailer_options *opts, + struct string_list *filter_list, + struct strbuf *sepbuf, + struct strbuf *kvsepbuf, + const char **arg, + char **invalid_arg) +{ + for (;;) { + const char *argval; + size_t arglen; + + if (**arg == ')') + break; + + if (match_placeholder_arg_value(*arg, "key", arg, &argval, &arglen)) { + uintptr_t len = arglen; + + if (!argval) + return -1; + + if (len && argval[len - 1] == ':') + len--; + string_list_append(filter_list, argval)->util = (char *)len; + + opts->filter = format_trailer_match_cb; + opts->filter_data = filter_list; + opts->only_trailers = 1; + } else if (match_placeholder_arg_value(*arg, "separator", arg, &argval, &arglen)) { + char *fmt; + + strbuf_reset(sepbuf); + fmt = xstrndup(argval, arglen); + strbuf_expand(sepbuf, fmt, strbuf_expand_literal_cb, NULL); + free(fmt); + opts->separator = sepbuf; + } else if (match_placeholder_arg_value(*arg, "key_value_separator", arg, &argval, &arglen)) { + char *fmt; + + strbuf_reset(kvsepbuf); + fmt = xstrndup(argval, arglen); + strbuf_expand(kvsepbuf, fmt, strbuf_expand_literal_cb, NULL); + free(fmt); + opts->key_value_separator = kvsepbuf; + } else if (!match_placeholder_bool_arg(*arg, "only", arg, &opts->only_trailers) && + !match_placeholder_bool_arg(*arg, "unfold", arg, &opts->unfold) && + !match_placeholder_bool_arg(*arg, "keyonly", arg, &opts->key_only) && + !match_placeholder_bool_arg(*arg, "valueonly", arg, &opts->value_only)) { + if (invalid_arg) { + size_t len = strcspn(*arg, ",)"); + *invalid_arg = xstrndup(*arg, len); + } + return -1; + } + } + return 0; +} + static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ const char *placeholder, void *context) @@ -1373,10 +1431,13 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ return 2; } - /* For the rest we have to parse the commit header. */ - if (!c->commit_header_parsed) + if (!c->commit_header_parsed) { + msg = c->message = + repo_logmsg_reencode(c->repository, commit, + &c->commit_encoding, "UTF-8"); parse_commit_header(c); + } switch (placeholder[0]) { case 'a': /* author ... */ @@ -1425,45 +1486,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ if (*arg == ':') { arg++; - for (;;) { - const char *argval; - size_t arglen; - - if (match_placeholder_arg_value(arg, "key", &arg, &argval, &arglen)) { - uintptr_t len = arglen; - - if (!argval) - goto trailer_out; - - if (len && argval[len - 1] == ':') - len--; - string_list_append(&filter_list, argval)->util = (char *)len; - - opts.filter = format_trailer_match_cb; - opts.filter_data = &filter_list; - opts.only_trailers = 1; - } else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) { - char *fmt; - - strbuf_reset(&sepbuf); - fmt = xstrndup(argval, arglen); - strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL); - free(fmt); - opts.separator = &sepbuf; - } else if (match_placeholder_arg_value(arg, "key_value_separator", &arg, &argval, &arglen)) { - char *fmt; - - strbuf_reset(&kvsepbuf); - fmt = xstrndup(argval, arglen); - strbuf_expand(&kvsepbuf, fmt, strbuf_expand_literal_cb, NULL); - free(fmt); - opts.key_value_separator = &kvsepbuf; - } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) && - !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) && - !match_placeholder_bool_arg(arg, "keyonly", &arg, &opts.key_only) && - !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only)) - break; - } + if (format_set_trailers_options(&opts, &filter_list, &sepbuf, &kvsepbuf, &arg, NULL)) + goto trailer_out; } if (*arg == ')') { format_trailers_from_commit(sb, msg + c->subject_off, &opts); @@ -1667,6 +1691,7 @@ void repo_format_commit_message(struct repository *r, const struct pretty_print_context *pretty_ctx) { struct format_commit_context context = { + .repository = r, .commit = commit, .pretty_ctx = pretty_ctx, .wrap_start = sb->len @@ -1674,18 +1699,14 @@ void repo_format_commit_message(struct repository *r, const char *output_enc = pretty_ctx->output_encoding; const char *utf8 = "UTF-8"; - /* - * convert a commit message to UTF-8 first - * as far as 'format_commit_item' assumes it in UTF-8 - */ - context.message = repo_logmsg_reencode(r, commit, - &context.commit_encoding, - utf8); - strbuf_expand(sb, format, format_commit_item, &context); rewrap_message_tail(sb, &context, 0, 0, 0); - /* then convert a commit message to an actual output encoding */ + /* + * Convert output to an actual output encoding; note that + * format_commit_item() will always use UTF-8, so we don't + * have to bother if that's what the output wants. + */ if (output_enc) { if (same_encoding(utf8, output_enc)) output_enc = NULL; |