Skip to content

Commit b03cd16

Browse files
committed
Merge branch 'tb/show-trailers-in-ref-filter'
"git for-each-ref --format=..." learned a new format element, %(trailers), to show only the commit log trailer part of the log message. * tb/show-trailers-in-ref-filter: ref-filter.c: parse trailers arguments with %(contents) atom ref-filter.c: use trailer_opts to format trailers t6300: refactor %(trailers) tests doc: use "`<literal>`"-style quoting for literal strings doc: 'trailers' is the preferred way to format trailers t4205: unfold across multiple lines
2 parents 54bd705 + 7a5edbd commit b03cd16

File tree

4 files changed

+122
-17
lines changed

4 files changed

+122
-17
lines changed

Documentation/git-for-each-ref.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,15 @@ and `date` to extract the named component.
218218
The complete message in a commit and tag object is `contents`.
219219
Its first line is `contents:subject`, where subject is the concatenation
220220
of all lines of the commit message up to the first blank line. The next
221-
line is 'contents:body', where body is all of the lines after the first
221+
line is `contents:body`, where body is all of the lines after the first
222222
blank line. The optional GPG signature is `contents:signature`. The
223223
first `N` lines of the message is obtained using `contents:lines=N`.
224224
Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
225-
are obtained as 'contents:trailers'.
225+
are obtained as `trailers` (or by using the historical alias
226+
`contents:trailers`). Non-trailer lines from the trailer block can be omitted
227+
with `trailers:only`. Whitespace-continuations can be removed from trailers so
228+
that each trailer appears on a line by itself with its full content with
229+
`trailers:unfold`. Both can be used together as `trailers:unfold,only`.
226230

227231
For sorting purposes, fields with numeric values sort in numeric order
228232
(`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).

ref-filter.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ static struct used_atom {
8282
} remote_ref;
8383
struct {
8484
enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
85+
struct process_trailer_options trailer_opts;
8586
unsigned int nlines;
8687
} contents;
8788
struct {
@@ -182,9 +183,23 @@ static void subject_atom_parser(const struct ref_format *format, struct used_ato
182183

183184
static void trailers_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)
184185
{
185-
if (arg)
186-
die(_("%%(trailers) does not take arguments"));
186+
struct string_list params = STRING_LIST_INIT_DUP;
187+
int i;
188+
189+
if (arg) {
190+
string_list_split(&params, arg, ',', -1);
191+
for (i = 0; i < params.nr; i++) {
192+
const char *s = params.items[i].string;
193+
if (!strcmp(s, "unfold"))
194+
atom->u.contents.trailer_opts.unfold = 1;
195+
else if (!strcmp(s, "only"))
196+
atom->u.contents.trailer_opts.only_trailers = 1;
197+
else
198+
die(_("unknown %%(trailers) argument: %s"), s);
199+
}
200+
}
187201
atom->u.contents.option = C_TRAILERS;
202+
string_list_clear(&params, 0);
188203
}
189204

190205
static void contents_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg)
@@ -197,9 +212,10 @@ static void contents_atom_parser(const struct ref_format *format, struct used_at
197212
atom->u.contents.option = C_SIG;
198213
else if (!strcmp(arg, "subject"))
199214
atom->u.contents.option = C_SUB;
200-
else if (!strcmp(arg, "trailers"))
201-
atom->u.contents.option = C_TRAILERS;
202-
else if (skip_prefix(arg, "lines=", &arg)) {
215+
else if (skip_prefix(arg, "trailers", &arg)) {
216+
skip_prefix(arg, ":", &arg);
217+
trailers_atom_parser(format, atom, *arg ? arg : NULL);
218+
} else if (skip_prefix(arg, "lines=", &arg)) {
203219
atom->u.contents.option = C_LINES;
204220
if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
205221
die(_("positive value expected contents:lines=%s"), arg);
@@ -1048,7 +1064,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
10481064
name++;
10491065
if (strcmp(name, "subject") &&
10501066
strcmp(name, "body") &&
1051-
strcmp(name, "trailers") &&
1067+
!starts_with(name, "trailers") &&
10521068
!starts_with(name, "contents"))
10531069
continue;
10541070
if (!subpos)
@@ -1073,13 +1089,12 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
10731089
append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines);
10741090
v->s = strbuf_detach(&s, NULL);
10751091
} else if (atom->u.contents.option == C_TRAILERS) {
1076-
struct trailer_info info;
1092+
struct strbuf s = STRBUF_INIT;
1093+
1094+
/* Format the trailer info according to the trailer_opts given */
1095+
format_trailers_from_commit(&s, subpos, &atom->u.contents.trailer_opts);
10771096

1078-
/* Search for trailer info */
1079-
trailer_info_get(&info, subpos);
1080-
v->s = xmemdupz(info.trailer_start,
1081-
info.trailer_end - info.trailer_start);
1082-
trailer_info_release(&info);
1097+
v->s = strbuf_detach(&s, NULL);
10831098
} else if (atom->u.contents.option == C_BARE)
10841099
v->s = xstrdup(subpos);
10851100
}

t/t4205-log-pretty-formats.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ Signed-off-by: A U Thor
544544
EOF
545545

546546
unfold () {
547-
perl -0pe 's/\n\s+/ /'
547+
perl -0pe 's/\n\s+/ /g'
548548
}
549549

550550
test_expect_success 'set up trailer tests' '

t/t6300-for-each-ref.sh

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,18 +605,104 @@ test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
605605
cat >trailers <<EOF
606606
Reviewed-by: A U Thor <[email protected]>
607607
Signed-off-by: A U Thor <[email protected]>
608+
[ v2 updated patch description ]
609+
Acked-by: A U Thor
610+
608611
EOF
609612

610-
test_expect_success 'basic atom: head contents:trailers' '
613+
unfold () {
614+
perl -0pe 's/\n\s+/ /g'
615+
}
616+
617+
test_expect_success 'set up trailers for next test' '
611618
echo "Some contents" > two &&
612619
git add two &&
613-
git commit -F - <<-EOF &&
620+
git commit -F - <<-EOF
614621
trailers: this commit message has trailers
615622
616623
Some message contents
617624
618625
$(cat trailers)
619626
EOF
627+
'
628+
629+
test_expect_success '%(trailers:unfold) unfolds trailers' '
630+
git for-each-ref --format="%(trailers:unfold)" refs/heads/master >actual &&
631+
{
632+
unfold <trailers
633+
echo
634+
} >expect &&
635+
test_cmp expect actual
636+
'
637+
638+
test_expect_success '%(trailers:only) shows only "key: value" trailers' '
639+
git for-each-ref --format="%(trailers:only)" refs/heads/master >actual &&
640+
{
641+
grep -v patch.description <trailers &&
642+
echo
643+
} >expect &&
644+
test_cmp expect actual
645+
'
646+
647+
test_expect_success '%(trailers:only) and %(trailers:unfold) work together' '
648+
git for-each-ref --format="%(trailers:only,unfold)" refs/heads/master >actual &&
649+
git for-each-ref --format="%(trailers:unfold,only)" refs/heads/master >reverse &&
650+
test_cmp actual reverse &&
651+
{
652+
grep -v patch.description <trailers | unfold &&
653+
echo
654+
} >expect &&
655+
test_cmp expect actual
656+
'
657+
658+
test_expect_success '%(contents:trailers:unfold) unfolds trailers' '
659+
git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual &&
660+
{
661+
unfold <trailers
662+
echo
663+
} >expect &&
664+
test_cmp expect actual
665+
'
666+
667+
test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' '
668+
git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual &&
669+
{
670+
grep -v patch.description <trailers &&
671+
echo
672+
} >expect &&
673+
test_cmp expect actual
674+
'
675+
676+
test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' '
677+
git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual &&
678+
git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse &&
679+
test_cmp actual reverse &&
680+
{
681+
grep -v patch.description <trailers | unfold &&
682+
echo
683+
} >expect &&
684+
test_cmp expect actual
685+
'
686+
687+
test_expect_success '%(trailers) rejects unknown trailers arguments' '
688+
# error message cannot be checked under i18n
689+
cat >expect <<-EOF &&
690+
fatal: unknown %(trailers) argument: unsupported
691+
EOF
692+
test_must_fail git for-each-ref --format="%(trailers:unsupported)" 2>actual &&
693+
test_i18ncmp expect actual
694+
'
695+
696+
test_expect_success '%(contents:trailers) rejects unknown trailers arguments' '
697+
# error message cannot be checked under i18n
698+
cat >expect <<-EOF &&
699+
fatal: unknown %(trailers) argument: unsupported
700+
EOF
701+
test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual &&
702+
test_i18ncmp expect actual
703+
'
704+
705+
test_expect_success 'basic atom: head contents:trailers' '
620706
git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual &&
621707
sanitize_pgp <actual >actual.clean &&
622708
# git for-each-ref ends with a blank line

0 commit comments

Comments
 (0)