Skip to content

Commit 0b691d8

Browse files
wandersgitster
authored andcommitted
pretty: add support for separator option in %(trailers)
By default trailer lines are terminated by linebreaks ('\n'). By specifying the new 'separator' option they will instead be separated by user provided string and have separator semantics rather than terminator semantics. The separator string can contain the literal formatting codes %n and %xNN allowing it to be things that are otherwise hard to type such as %x00, or comma and end-parenthesis which would break parsing. E.g: $ git log --pretty='%(trailers:key=Reviewed-by,valueonly,separator=%x00)' Signed-off-by: Anders Waldenborg <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fd2015b commit 0b691d8

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

Documentation/pretty-formats.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ endif::git-rev-list[]
239239
`false`, `off`, `no` to show the non-trailer lines. If option is
240240
given without value it is enabled. If given multiple times the last
241241
value is used.
242+
** 'separator=<SEP>': specify a separator inserted between trailer
243+
lines. When this option is not given each trailer line is
244+
terminated with a line feed character. The string SEP may contain
245+
the literal formatting codes described above. To use comma as
246+
separator one must use `%x2C` as it would otherwise be parsed as
247+
next option. If separator option is given multiple times only the
248+
last one is used. E.g., `%(trailers:key=Ticket,separator=%x2C )`
249+
shows all trailer lines whose key is "Ticket" separated by a comma
250+
and a space.
242251
** 'unfold[=val]': make it behave as if interpret-trailer's `--unfold`
243252
option was given. In same way as to for `only` it can be followed
244253
by an equal sign and explicit value. E.g.,

pretty.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
13611361
if (skip_prefix(placeholder, "(trailers", &arg)) {
13621362
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
13631363
struct string_list filter_list = STRING_LIST_INIT_NODUP;
1364+
struct strbuf sepbuf = STRBUF_INIT;
13641365
size_t ret = 0;
13651366

13661367
opts.no_divider = 1;
@@ -1384,6 +1385,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
13841385
opts.filter = format_trailer_match_cb;
13851386
opts.filter_data = &filter_list;
13861387
opts.only_trailers = 1;
1388+
} else if (match_placeholder_arg_value(arg, "separator", &arg, &argval, &arglen)) {
1389+
char *fmt;
1390+
1391+
strbuf_reset(&sepbuf);
1392+
fmt = xstrndup(argval, arglen);
1393+
strbuf_expand(&sepbuf, fmt, strbuf_expand_literal_cb, NULL);
1394+
free(fmt);
1395+
opts.separator = &sepbuf;
13871396
} else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
13881397
!match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
13891398
!match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
@@ -1396,6 +1405,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
13961405
}
13971406
trailer_out:
13981407
string_list_clear(&filter_list, 0);
1408+
strbuf_release(&sepbuf);
13991409
return ret;
14001410
}
14011411

t/t4205-log-pretty-formats.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,42 @@ test_expect_success '%(trailers:key=foo,valueonly) shows only value' '
679679
test_cmp expect actual
680680
'
681681

682+
test_expect_success 'pretty format %(trailers:separator) changes separator' '
683+
git log --no-walk --pretty=format:"X%(trailers:separator=%x00,unfold)X" >actual &&
684+
printf "XSigned-off-by: A U Thor <[email protected]>\0Acked-by: A U Thor <[email protected]>\0[ v2 updated patch description ]\0Signed-off-by: A U Thor <[email protected]>X" >expect &&
685+
test_cmp expect actual
686+
'
687+
688+
test_expect_success 'pretty format %(trailers) combining separator/key/valueonly' '
689+
git commit --allow-empty -F - <<-\EOF &&
690+
Important fix
691+
692+
The fix is explained here
693+
694+
Closes: #1234
695+
EOF
696+
697+
git commit --allow-empty -F - <<-\EOF &&
698+
Another fix
699+
700+
The fix is explained here
701+
702+
Closes: #567
703+
Closes: #890
704+
EOF
705+
706+
git commit --allow-empty -F - <<-\EOF &&
707+
Does not close any tickets
708+
EOF
709+
710+
git log --pretty="%s% (trailers:separator=%x2c%x20,key=Closes,valueonly)" HEAD~3.. >actual &&
711+
test_write_lines \
712+
"Does not close any tickets" \
713+
"Another fix #567, #890" \
714+
"Important fix #1234" >expect &&
715+
test_cmp expect actual
716+
'
717+
682718
test_expect_success 'trailer parsing not fooled by --- line' '
683719
git commit --allow-empty -F - <<-\EOF &&
684720
this is the subject

trailer.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,10 +1129,11 @@ static void format_trailer_info(struct strbuf *out,
11291129
const struct trailer_info *info,
11301130
const struct process_trailer_options *opts)
11311131
{
1132+
size_t origlen = out->len;
11321133
size_t i;
11331134

11341135
/* If we want the whole block untouched, we can take the fast path. */
1135-
if (!opts->only_trailers && !opts->unfold && !opts->filter) {
1136+
if (!opts->only_trailers && !opts->unfold && !opts->filter && !opts->separator) {
11361137
strbuf_add(out, info->trailer_start,
11371138
info->trailer_end - info->trailer_start);
11381139
return;
@@ -1150,16 +1151,26 @@ static void format_trailer_info(struct strbuf *out,
11501151
if (!opts->filter || opts->filter(&tok, opts->filter_data)) {
11511152
if (opts->unfold)
11521153
unfold_value(&val);
1154+
1155+
if (opts->separator && out->len != origlen)
1156+
strbuf_addbuf(out, opts->separator);
11531157
if (!opts->value_only)
11541158
strbuf_addf(out, "%s: ", tok.buf);
11551159
strbuf_addbuf(out, &val);
1156-
strbuf_addch(out, '\n');
1160+
if (!opts->separator)
1161+
strbuf_addch(out, '\n');
11571162
}
11581163
strbuf_release(&tok);
11591164
strbuf_release(&val);
11601165

11611166
} else if (!opts->only_trailers) {
1167+
if (opts->separator && out->len != origlen) {
1168+
strbuf_addbuf(out, opts->separator);
1169+
}
11621170
strbuf_addstr(out, trailer);
1171+
if (opts->separator) {
1172+
strbuf_rtrim(out);
1173+
}
11631174
}
11641175
}
11651176

trailer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct process_trailer_options {
7373
int unfold;
7474
int no_divider;
7575
int value_only;
76+
const struct strbuf *separator;
7677
int (*filter)(const struct strbuf *, void *);
7778
void *filter_data;
7879
};

0 commit comments

Comments
 (0)