Skip to content

Commit 06cf4f2

Browse files
committed
Merge branch 'jk/trailers-parse'
"git interpret-trailers" has been taught a "--parse" and a few other options to make it easier for scripts to grab existing trailer lines from a commit log message. * jk/trailers-parse: doc/interpret-trailers: fix "the this" typo pretty: support normalization options for %(trailers) t4205: refactor %(trailers) tests pretty: move trailer formatting to trailer.c interpret-trailers: add --parse convenience option interpret-trailers: add an option to unfold values interpret-trailers: add an option to show only existing trailers interpret-trailers: add an option to show only the trailers trailer: put process_trailers() options into a struct
2 parents bfd91b4 + 5a0d0c0 commit 06cf4f2

File tree

8 files changed

+314
-52
lines changed

8 files changed

+314
-52
lines changed

Documentation/git-interpret-trailers.txt

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,27 @@ git-interpret-trailers(1)
33

44
NAME
55
----
6-
git-interpret-trailers - help add structured information into commit messages
6+
git-interpret-trailers - add or parse structured information in commit messages
77

88
SYNOPSIS
99
--------
1010
[verse]
11-
'git interpret-trailers' [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]
11+
'git interpret-trailers' [options] [(--trailer <token>[(=|:)<value>])...] [<file>...]
12+
'git interpret-trailers' [options] [--parse] [<file>...]
1213

1314
DESCRIPTION
1415
-----------
15-
Help adding 'trailers' lines, that look similar to RFC 822 e-mail
16+
Help parsing or adding 'trailers' lines, that look similar to RFC 822 e-mail
1617
headers, at the end of the otherwise free-form part of a commit
1718
message.
1819

1920
This command reads some patches or commit messages from either the
20-
<file> arguments or the standard input if no <file> is specified. Then
21-
this command applies the arguments passed using the `--trailer`
22-
option, if any, to the commit message part of each input file. The
23-
result is emitted on the standard output.
21+
<file> arguments or the standard input if no <file> is specified. If
22+
`--parse` is specified, the output consists of the parsed trailers.
23+
24+
Otherwise, this command applies the arguments passed using the
25+
`--trailer` option, if any, to the commit message part of each input
26+
file. The result is emitted on the standard output.
2427

2528
Some configuration variables control the way the `--trailer` arguments
2629
are applied to each commit message and the way any existing trailer in
@@ -103,6 +106,22 @@ OPTIONS
103106
and applies to all '--trailer' options until the next occurrence of
104107
'--if-missing' or '--no-if-missing'.
105108

109+
--only-trailers::
110+
Output only the trailers, not any other parts of the input.
111+
112+
--only-input::
113+
Output only trailers that exist in the input; do not add any
114+
from the command-line or by following configured `trailer.*`
115+
rules.
116+
117+
--unfold::
118+
Remove any whitespace-continuation in trailers, so that each
119+
trailer appears on a line by itself with its full content.
120+
121+
--parse::
122+
A convenience alias for `--only-trailers --only-input
123+
--unfold`.
124+
106125
CONFIGURATION VARIABLES
107126
-----------------------
108127

Documentation/pretty-formats.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,10 @@ endif::git-rev-list[]
205205
- '%><(<N>)', '%><|(<N>)': similar to '% <(<N>)', '%<|(<N>)'
206206
respectively, but padding both sides (i.e. the text is centered)
207207
- %(trailers): display the trailers of the body as interpreted by
208-
linkgit:git-interpret-trailers[1]
208+
linkgit:git-interpret-trailers[1]. If the `:only` option is given,
209+
omit non-trailer lines from the trailer block. If the `:unfold`
210+
option is given, behave as if interpret-trailer's `--unfold` option
211+
was given. E.g., `%(trailers:only:unfold)` to do both.
209212

210213
NOTE: Some placeholders may depend on other options given to the
211214
revision traversal engine. For example, the `%g*` reflog options will

builtin/interpret-trailers.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,24 @@ static int option_parse_trailer(const struct option *opt,
7373
return 0;
7474
}
7575

76+
static int parse_opt_parse(const struct option *opt, const char *arg,
77+
int unset)
78+
{
79+
struct process_trailer_options *v = opt->value;
80+
v->only_trailers = 1;
81+
v->only_input = 1;
82+
v->unfold = 1;
83+
return 0;
84+
}
85+
7686
int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
7787
{
78-
int in_place = 0;
79-
int trim_empty = 0;
88+
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
8089
LIST_HEAD(trailers);
8190

8291
struct option options[] = {
83-
OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
84-
OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
92+
OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
93+
OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
8594

8695
OPT_CALLBACK(0, "where", NULL, N_("action"),
8796
N_("where to place the new trailer"), option_parse_where),
@@ -90,6 +99,11 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
9099
OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
91100
N_("action if trailer is missing"), option_parse_if_missing),
92101

102+
OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
103+
OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")),
104+
OPT_BOOL(0, "unfold", &opts.unfold, N_("join whitespace-continued values")),
105+
{ OPTION_CALLBACK, 0, "parse", &opts, NULL, N_("set parsing options"),
106+
PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse },
93107
OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"),
94108
N_("trailer(s) to add"), option_parse_trailer),
95109
OPT_END()
@@ -98,14 +112,20 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
98112
argc = parse_options(argc, argv, prefix, options,
99113
git_interpret_trailers_usage, 0);
100114

115+
if (opts.only_input && !list_empty(&trailers))
116+
usage_msg_opt(
117+
_("--trailer with --only-input does not make sense"),
118+
git_interpret_trailers_usage,
119+
options);
120+
101121
if (argc) {
102122
int i;
103123
for (i = 0; i < argc; i++)
104-
process_trailers(argv[i], in_place, trim_empty, &trailers);
124+
process_trailers(argv[i], &opts, &trailers);
105125
} else {
106-
if (in_place)
126+
if (opts.in_place)
107127
die(_("no input file given for in-place editing"));
108-
process_trailers(NULL, in_place, trim_empty, &trailers);
128+
process_trailers(NULL, &opts, &trailers);
109129
}
110130

111131
new_trailers_clear(&trailers);

pretty.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -871,16 +871,6 @@ const char *format_subject(struct strbuf *sb, const char *msg,
871871
return msg;
872872
}
873873

874-
static void format_trailers(struct strbuf *sb, const char *msg)
875-
{
876-
struct trailer_info info;
877-
878-
trailer_info_get(&info, msg);
879-
strbuf_add(sb, info.trailer_start,
880-
info.trailer_end - info.trailer_start);
881-
trailer_info_release(&info);
882-
}
883-
884874
static void parse_commit_message(struct format_commit_context *c)
885875
{
886876
const char *msg = c->message + c->message_off;
@@ -1074,6 +1064,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
10741064
const struct commit *commit = c->commit;
10751065
const char *msg = c->message;
10761066
struct commit_list *p;
1067+
const char *arg;
10771068
int ch;
10781069

10791070
/* these are independent of the commit */
@@ -1292,9 +1283,18 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
12921283
return 1;
12931284
}
12941285

1295-
if (starts_with(placeholder, "(trailers)")) {
1296-
format_trailers(sb, msg + c->subject_off);
1297-
return strlen("(trailers)");
1286+
if (skip_prefix(placeholder, "(trailers", &arg)) {
1287+
struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
1288+
while (*arg == ':') {
1289+
if (skip_prefix(arg, ":only", &arg))
1290+
opts.only_trailers = 1;
1291+
else if (skip_prefix(arg, ":unfold", &arg))
1292+
opts.unfold = 1;
1293+
}
1294+
if (*arg == ')') {
1295+
format_trailers_from_commit(sb, msg + c->subject_off, &opts);
1296+
return arg - placeholder + 1;
1297+
}
12981298
}
12991299

13001300
return 0; /* unknown placeholder */

t/t4205-log-pretty-formats.sh

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -539,25 +539,62 @@ cat >trailers <<EOF
539539
Signed-off-by: A U Thor <[email protected]>
540540
Acked-by: A U Thor <[email protected]>
541541
[ v2 updated patch description ]
542-
Signed-off-by: A U Thor <[email protected]>
542+
Signed-off-by: A U Thor
543+
543544
EOF
544545

545-
test_expect_success 'pretty format %(trailers) shows trailers' '
546+
unfold () {
547+
perl -0pe 's/\n\s+/ /'
548+
}
549+
550+
test_expect_success 'set up trailer tests' '
546551
echo "Some contents" >trailerfile &&
547552
git add trailerfile &&
548-
git commit -F - <<-EOF &&
553+
git commit -F - <<-EOF
549554
trailers: this commit message has trailers
550555
551556
This commit is a test commit with trailers at the end. We parse this
552-
message and display the trailers using %bT
557+
message and display the trailers using %(trailers).
553558
554559
$(cat trailers)
555560
EOF
561+
'
562+
563+
test_expect_success 'pretty format %(trailers) shows trailers' '
556564
git log --no-walk --pretty="%(trailers)" >actual &&
557-
cat >expect <<-EOF &&
558-
$(cat trailers)
565+
{
566+
cat trailers &&
567+
echo
568+
} >expect &&
569+
test_cmp expect actual
570+
'
559571

560-
EOF
572+
test_expect_success '%(trailers:only) shows only "key: value" trailers' '
573+
git log --no-walk --pretty="%(trailers:only)" >actual &&
574+
{
575+
grep -v patch.description <trailers &&
576+
echo
577+
} >expect &&
578+
test_cmp expect actual
579+
'
580+
581+
test_expect_success '%(trailers:unfold) unfolds trailers' '
582+
git log --no-walk --pretty="%(trailers:unfold)" >actual &&
583+
{
584+
unfold <trailers &&
585+
echo
586+
} >expect &&
587+
test_cmp expect actual
588+
'
589+
590+
test_expect_success ':only and :unfold work together' '
591+
git log --no-walk --pretty="%(trailers:only:unfold)" >actual &&
592+
git log --no-walk --pretty="%(trailers:unfold:only)" >reverse &&
593+
test_cmp actual reverse &&
594+
{
595+
grep -v patch.description <trailers | unfold &&
596+
echo
597+
} >expect &&
561598
test_cmp expect actual
562599
'
563600

t/t7513-interpret-trailers.sh

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,4 +1341,80 @@ test_expect_success 'with cut line' '
13411341
test_cmp expected actual
13421342
'
13431343

1344+
test_expect_success 'only trailers' '
1345+
git config trailer.sign.command "echo config-value" &&
1346+
cat >expected <<-\EOF &&
1347+
existing: existing-value
1348+
sign: config-value
1349+
added: added-value
1350+
EOF
1351+
git interpret-trailers \
1352+
--trailer added:added-value \
1353+
--only-trailers >actual <<-\EOF &&
1354+
my subject
1355+
1356+
my body
1357+
1358+
existing: existing-value
1359+
EOF
1360+
test_cmp expected actual
1361+
'
1362+
1363+
test_expect_success 'only-trailers omits non-trailer in middle of block' '
1364+
git config trailer.sign.command "echo config-value" &&
1365+
cat >expected <<-\EOF &&
1366+
Signed-off-by: nobody <nobody@nowhere>
1367+
Signed-off-by: somebody <somebody@somewhere>
1368+
sign: config-value
1369+
EOF
1370+
git interpret-trailers --only-trailers >actual <<-\EOF &&
1371+
subject
1372+
1373+
it is important that the trailers below are signed-off-by
1374+
so that they meet the "25% trailers Git knows about" heuristic
1375+
1376+
Signed-off-by: nobody <nobody@nowhere>
1377+
this is not a trailer
1378+
Signed-off-by: somebody <somebody@somewhere>
1379+
EOF
1380+
test_cmp expected actual
1381+
'
1382+
1383+
test_expect_success 'only input' '
1384+
git config trailer.sign.command "echo config-value" &&
1385+
cat >expected <<-\EOF &&
1386+
existing: existing-value
1387+
EOF
1388+
git interpret-trailers \
1389+
--only-trailers --only-input >actual <<-\EOF &&
1390+
my subject
1391+
1392+
my body
1393+
1394+
existing: existing-value
1395+
EOF
1396+
test_cmp expected actual
1397+
'
1398+
1399+
test_expect_success 'unfold' '
1400+
cat >expected <<-\EOF &&
1401+
foo: continued across several lines
1402+
EOF
1403+
# pass through tr to make leading and trailing whitespace more obvious
1404+
tr _ " " <<-\EOF |
1405+
my subject
1406+
1407+
my body
1408+
1409+
foo:_
1410+
__continued
1411+
___across
1412+
____several
1413+
_____lines
1414+
___
1415+
EOF
1416+
git interpret-trailers --only-trailers --only-input --unfold >actual &&
1417+
test_cmp expected actual
1418+
'
1419+
13441420
test_done

0 commit comments

Comments
 (0)