This new format placeholder allows displaying only a single trailer. The formatting done is similar to what is done for --decorate/%d using parentheses and comma separation. It's intended use is for things like ticket references in trailers. So with a commit with a message like: > Some good commit > > Ticket: XYZ-123 running: $ git log --pretty="%H %s% (trailer:Ticket)" will give: > 123456789a Some good commit (Ticket: XYZ-123) Signed-off-by: Anders Waldenborg <anders@xxxxxxx> --- Documentation/pretty-formats.txt | 4 ++++ pretty.c | 16 +++++++++++++ t/t4205-log-pretty-formats.sh | 40 ++++++++++++++++++++++++++++++++ trailer.c | 18 ++++++++++++-- trailer.h | 1 + 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 6109ef09aa..a46d0c0717 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -211,6 +211,10 @@ endif::git-rev-list[] If the `unfold` option is given, behave as if interpret-trailer's `--unfold` option was given. E.g., `%(trailers:only,unfold)` to do both. +- %(trailer:<t>): display the specified trailer in parentheses (like + %d does for refnames). If there are multiple entries of that trailer + they are shown comma separated. If there are no matching trailers + nothing is displayed. NOTE: Some placeholders may depend on other options given to the revision traversal engine. For example, the `%g*` reflog options will diff --git a/pretty.c b/pretty.c index 8ca29e9281..61ae34ced4 100644 --- a/pretty.c +++ b/pretty.c @@ -1324,6 +1324,22 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ } } + if (skip_prefix(placeholder, "(trailer:", &arg)) { + struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; + opts.no_divider = 1; + opts.only_trailers = 1; + opts.unfold = 1; + + const char *end = strchr(arg, ')'); + if (!end) + return 0; + + opts.filter_trailer = xstrndup(arg, end - arg); + format_trailers_from_commit(sb, msg + c->subject_off, &opts); + free(opts.filter_trailer); + return end - placeholder + 1; + } + return 0; /* unknown placeholder */ } diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index 978a8a66ff..e929f820e7 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -598,6 +598,46 @@ test_expect_success ':only and :unfold work together' ' test_cmp expect actual ' +test_expect_success 'pretty format %(trailer:foo) shows that trailer' ' + git log --no-walk --pretty="%(trailer:Acked-By)" >actual && + { + echo "(Acked-By: A U Thor <author@xxxxxxxxxxx>)" + } >expect && + test_cmp expect actual +' + +test_expect_success '%(trailer:nonexistant) becomes empty' ' + git log --no-walk --pretty="x%(trailer:Nacked-By)x" >actual && + { + echo "xx" + } >expect && + test_cmp expect actual +' + +test_expect_success '% (trailer:nonexistant) with space becomes empty' ' + git log --no-walk --pretty="x% (trailer:Nacked-By)x" >actual && + { + echo "xx" + } >expect && + test_cmp expect actual +' + +test_expect_success '% (trailer:foo) with space adds space before' ' + git log --no-walk --pretty="x% (trailer:Acked-By)x" >actual && + { + echo "x (Acked-By: A U Thor <author@xxxxxxxxxxx>)x" + } >expect && + test_cmp expect actual +' + +test_expect_success '%(trailer:foo) with multiple lines becomes comma separated and unwrapped' ' + git log --no-walk --pretty="%(trailer:Signed-Off-By)" >actual && + { + echo "(Signed-Off-By: A U Thor <author@xxxxxxxxxxx>, A U Thor <author@xxxxxxxxxxx>)" + } >expect && + test_cmp expect actual +' + test_expect_success 'trailer parsing not fooled by --- line' ' git commit --allow-empty -F - <<-\EOF && this is the subject diff --git a/trailer.c b/trailer.c index 0796f326b3..d337bca8dd 100644 --- a/trailer.c +++ b/trailer.c @@ -1138,6 +1138,7 @@ static void format_trailer_info(struct strbuf *out, return; } + int printed_first = 0; for (i = 0; i < info->trailer_nr; i++) { char *trailer = info->trailers[i]; ssize_t separator_pos = find_separator(trailer, separators); @@ -1150,7 +1151,19 @@ static void format_trailer_info(struct strbuf *out, if (opts->unfold) unfold_value(&val); - strbuf_addf(out, "%s: %s\n", tok.buf, val.buf); + if (opts->filter_trailer) { + if (!strcasecmp (tok.buf, opts->filter_trailer)) { + if (!printed_first) { + strbuf_addf(out, "(%s: ", opts->filter_trailer); + printed_first = 1; + } else { + strbuf_addstr(out, ", "); + } + strbuf_addstr(out, val.buf); + } + } else { + strbuf_addf(out, "%s: %s\n", tok.buf, val.buf); + } strbuf_release(&tok); strbuf_release(&val); @@ -1158,7 +1171,8 @@ static void format_trailer_info(struct strbuf *out, strbuf_addstr(out, trailer); } } - + if (printed_first) + strbuf_addstr(out, ")"); } void format_trailers_from_commit(struct strbuf *out, const char *msg, diff --git a/trailer.h b/trailer.h index b997739649..852c79d449 100644 --- a/trailer.h +++ b/trailer.h @@ -72,6 +72,7 @@ struct process_trailer_options { int only_input; int unfold; int no_divider; + char *filter_trailer; }; #define PROCESS_TRAILER_OPTIONS_INIT {0} -- 2.17.1