ref-filter.c: parse trailers arguments with %(contents) atom

The %(contents) atom takes a contents "field" as its argument. Since
"trailers" is one of those fields, extend contents_atom_parser to parse
"trailers"'s arguments when used through "%(contents)", like:

  %(contents:trailers:unfold,only)

A caveat: trailers_atom_parser expects NULL when no arguments are given
(see: `parse_ref_filter_atom`). This is because string_list_split (given
a maxsplit of -1) returns a 1-ary string_list* containing the given
string if the delimiter could not be found using `strchr`.

To simulate this behavior without teaching trailers_atom_parser to
accept strings with length zero, conditionally pass NULL to
trailers_atom_parser if the arguments portion of the argument to
%(contents) is empty.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Taylor Blau 2017-10-01 22:25:24 -07:00 committed by Junio C Hamano
parent 67a20a0010
commit 7a5edbdb74
2 changed files with 42 additions and 3 deletions

View file

@ -212,9 +212,10 @@ static void contents_atom_parser(const struct ref_format *format, struct used_at
atom->u.contents.option = C_SIG;
else if (!strcmp(arg, "subject"))
atom->u.contents.option = C_SUB;
else if (!strcmp(arg, "trailers"))
atom->u.contents.option = C_TRAILERS;
else if (skip_prefix(arg, "lines=", &arg)) {
else if (skip_prefix(arg, "trailers", &arg)) {
skip_prefix(arg, ":", &arg);
trailers_atom_parser(format, atom, *arg ? arg : NULL);
} else if (skip_prefix(arg, "lines=", &arg)) {
atom->u.contents.option = C_LINES;
if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
die(_("positive value expected contents:lines=%s"), arg);

View file

@ -655,6 +655,35 @@ test_expect_success '%(trailers:only) and %(trailers:unfold) work together' '
test_cmp expect actual
'
test_expect_success '%(contents:trailers:unfold) unfolds trailers' '
git for-each-ref --format="%(contents:trailers:unfold)" refs/heads/master >actual &&
{
unfold <trailers
echo
} >expect &&
test_cmp expect actual
'
test_expect_success '%(contents:trailers:only) shows only "key: value" trailers' '
git for-each-ref --format="%(contents:trailers:only)" refs/heads/master >actual &&
{
grep -v patch.description <trailers &&
echo
} >expect &&
test_cmp expect actual
'
test_expect_success '%(contents:trailers:only) and %(contents:trailers:unfold) work together' '
git for-each-ref --format="%(contents:trailers:only,unfold)" refs/heads/master >actual &&
git for-each-ref --format="%(contents:trailers:unfold,only)" refs/heads/master >reverse &&
test_cmp actual reverse &&
{
grep -v patch.description <trailers | unfold &&
echo
} >expect &&
test_cmp expect actual
'
test_expect_success '%(trailers) rejects unknown trailers arguments' '
# error message cannot be checked under i18n
cat >expect <<-EOF &&
@ -664,6 +693,15 @@ test_expect_success '%(trailers) rejects unknown trailers arguments' '
test_i18ncmp expect actual
'
test_expect_success '%(contents:trailers) rejects unknown trailers arguments' '
# error message cannot be checked under i18n
cat >expect <<-EOF &&
fatal: unknown %(trailers) argument: unsupported
EOF
test_must_fail git for-each-ref --format="%(contents:trailers:unsupported)" 2>actual &&
test_i18ncmp expect actual
'
test_expect_success 'basic atom: head contents:trailers' '
git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual &&
sanitize_pgp <actual >actual.clean &&