interpret-trailers: add an option to show only the trailers
In theory it's easy for any reader who wants to parse trailers to do so. But there are a lot of subtle corner cases around what counts as a trailer, when the trailer block begins and ends, etc. Since interpret-trailers already has our parsing logic, let's let callers ask it to just output the trailers. They still have to parse the "key: value" lines, but at least they can ignore all of the other corner cases. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Aug 15, 2017 at 06:23 UTC
56c493ed1b9c067813fb95ff7cd4f69c7c1d2e36
5 files changed
+58
-9
Documentation/git-interpret-trailers.txt
+3
@@ -80,6 +80,9 @@ OPTIONS
80
trailer to the input messages. See the description of this
81
command.
82
83
+--only-trailers::
84
+ Output only the trailers, not any other parts of the input.
85
+
86
CONFIGURATION VARIABLES
87
-----------------------
88
builtin/interpret-trailers.c
+1
@@ -24,6 +24,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
24
struct option options[] = {
25
OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
26
OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
27
+ OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
28
OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
29
N_("trailer(s) to add")),
30
OPT_END()
t/t7513-interpret-trailers.sh
+39
@@ -1275,4 +1275,43 @@ test_expect_success 'with cut line' '
1275
test_cmp expected actual
1276
'
1277
1278
+test_expect_success 'only trailers' '
1279
+ git config trailer.sign.command "echo config-value" &&
1280
+ cat >expected <<-\EOF &&
1281
+ existing: existing-value
1282
+ sign: config-value
1283
+ added: added-value
1284
+ EOF
1285
+ git interpret-trailers \
1286
+ --trailer added:added-value \
1287
+ --only-trailers >actual <<-\EOF &&
1288
+ my subject
1289
+
1290
+ my body
1291
+
1292
+ existing: existing-value
1293
+ EOF
1294
+ test_cmp expected actual
1295
+'
1296
+
1297
+test_expect_success 'only-trailers omits non-trailer in middle of block' '
1298
+ git config trailer.sign.command "echo config-value" &&
1299
+ cat >expected <<-\EOF &&
1300
+ Signed-off-by: nobody <nobody@nowhere>
1301
+ Signed-off-by: somebody <somebody@somewhere>
1302
+ sign: config-value
1303
+ EOF
1304
+ git interpret-trailers --only-trailers >actual <<-\EOF &&
1305
+ subject
1306
+
1307
+ it is important that the trailers below are signed-off-by
1308
+ so that they meet the "25% trailers Git knows about" heuristic
1309
+
1310
+ Signed-off-by: nobody <nobody@nowhere>
1311
+ this is not a trailer
1312
+ Signed-off-by: somebody <somebody@somewhere>
1313
+ EOF
1314
+ test_cmp expected actual
1315
+'
1316
+
1317
test_done
trailer.c
+14
-9
@@ -163,13 +163,15 @@ static void print_tok_val(FILE *outfile, const char *tok, const char *val)
163
fprintf(outfile, "%s%c %s\n", tok, separators[0], val);
164
}
165
166
-static void print_all(FILE *outfile, struct list_head *head, int trim_empty)
166
+static void print_all(FILE *outfile, struct list_head *head,
167
+ const struct process_trailer_options *opts)
168
{
169
struct list_head *pos;
170
struct trailer_item *item;
171
list_for_each(pos, head) {
172
item = list_entry(pos, struct trailer_item, list);
172
- if (!trim_empty || strlen(item->value) > 0)
173
+ if ((!opts->trim_empty || strlen(item->value) > 0) &&
174
+ (!opts->only_trailers || item->token))
175
print_tok_val(outfile, item->token, item->value);
176
}
177
}
@@ -886,7 +888,8 @@ static int ends_with_blank_line(const char *buf, size_t len)
888
889
static int process_input_file(FILE *outfile,
890
const char *str,
889
- struct list_head *head)
891
+ struct list_head *head,
892
+ const struct process_trailer_options *opts)
893
{
894
struct trailer_info info;
895
struct strbuf tok = STRBUF_INIT;
@@ -896,9 +899,10 @@ static int process_input_file(FILE *outfile,
899
trailer_info_get(&info, str);
900
901
/* Print lines before the trailers as is */
899
- fwrite(str, 1, info.trailer_start - str, outfile);
902
+ if (!opts->only_trailers)
903
+ fwrite(str, 1, info.trailer_start - str, outfile);
904
901
- if (!info.blank_line_before_trailer)
905
+ if (!opts->only_trailers && !info.blank_line_before_trailer)
906
fprintf(outfile, "\n");
907
908
for (i = 0; i < info.trailer_nr; i++) {
@@ -913,7 +917,7 @@ static int process_input_file(FILE *outfile,
917
add_trailer_item(head,
918
strbuf_detach(&tok, NULL),
919
strbuf_detach(&val, NULL));
916
- } else {
920
+ } else if (!opts->only_trailers) {
921
strbuf_addstr(&val, trailer);
922
strbuf_strip_suffix(&val, "\n");
923
add_trailer_item(head,
@@ -985,18 +989,19 @@ void process_trailers(const char *file,
989
outfile = create_in_place_tempfile(file);
990
991
/* Print the lines before the trailers */
988
- trailer_end = process_input_file(outfile, sb.buf, &head);
992
+ trailer_end = process_input_file(outfile, sb.buf, &head, opts);
993
994
process_command_line_args(&arg_head, trailers);
995
996
process_trailers_lists(&head, &arg_head);
997
994
- print_all(outfile, &head, opts->trim_empty);
998
+ print_all(outfile, &head, opts);
999
1000
free_all(&head);
1001
1002
/* Print the lines after the trailers as is */
999
- fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
1003
+ if (!opts->only_trailers)
1004
+ fwrite(sb.buf + trailer_end, 1, sb.len - trailer_end, outfile);
1005
1006
if (opts->in_place)
1007
if (rename_tempfile(&trailers_tempfile, file))
trailer.h
+1
@@ -25,6 +25,7 @@ struct trailer_info {
25
struct process_trailer_options {
26
int in_place;
27
int trim_empty;
28
+ int only_trailers;
29
};
30
31
#define PROCESS_TRAILER_OPTIONS_INIT {0}