interpret-trailers: add an option to unfold values
The point of "--only-trailers" is to give a caller an output that's easy for them to parse. Getting rid of the non-trailer material helps, but we still may see more complicated syntax like whitespace continuation. Let's add an option to unfold any continuation, giving the output as a single "key: value" line per trailer. As a bonus, this could be used even without --only-trailers to clean up unusual formatting in the incoming data. 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
000023961a0c02d6e21dc51ea3484ff71abf1c74
5 files changed
+56
Documentation/git-interpret-trailers.txt
+4
@@ -88,6 +88,10 @@ OPTIONS
88
from the command-line or by following configured `trailer.*`
89
rules.
90
91
+--unfold::
92
+ Remove any whitespace-continuation in trailers, so that each
93
+ trailer appears on a line by itself with its full content.
94
+
95
CONFIGURATION VARIABLES
96
-----------------------
97
builtin/interpret-trailers.c
+1
@@ -26,6 +26,7 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
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_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")),
29
+ OPT_BOOL(0, "unfold", &opts.unfold, N_("join whitespace-continued values")),
30
OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
31
N_("trailer(s) to add")),
32
OPT_END()
t/t7513-interpret-trailers.sh
+21
@@ -1330,4 +1330,25 @@ test_expect_success 'only input' '
1330
test_cmp expected actual
1331
'
1332
1333
+test_expect_success 'unfold' '
1334
+ cat >expected <<-\EOF &&
1335
+ foo: continued across several lines
1336
+ EOF
1337
+ # pass through tr to make leading and trailing whitespace more obvious
1338
+ tr _ " " <<-\EOF |
1339
+ my subject
1340
+
1341
+ my body
1342
+
1343
+ foo:_
1344
+ __continued
1345
+ ___across
1346
+ ____several
1347
+ _____lines
1348
+ ___
1349
+ EOF
1350
+ git interpret-trailers --only-trailers --only-input --unfold >actual &&
1351
+ test_cmp expected actual
1352
+'
1353
+
1354
test_done
trailer.c
+29
@@ -886,6 +886,33 @@ static int ends_with_blank_line(const char *buf, size_t len)
886
return is_blank_line(buf + ll);
887
}
888
889
+static void unfold_value(struct strbuf *val)
890
+{
891
+ struct strbuf out = STRBUF_INIT;
892
+ size_t i;
893
+
894
+ strbuf_grow(&out, val->len);
895
+ i = 0;
896
+ while (i < val->len) {
897
+ char c = val->buf[i++];
898
+ if (c == '\n') {
899
+ /* Collapse continuation down to a single space. */
900
+ while (i < val->len && isspace(val->buf[i]))
901
+ i++;
902
+ strbuf_addch(&out, ' ');
903
+ } else {
904
+ strbuf_addch(&out, c);
905
+ }
906
+ }
907
+
908
+ /* Empty lines may have left us with whitespace cruft at the edges */
909
+ strbuf_trim(&out);
910
+
911
+ /* output goes back to val as if we modified it in-place */
912
+ strbuf_swap(&out, val);
913
+ strbuf_release(&out);
914
+}
915
+
916
static int process_input_file(FILE *outfile,
917
const char *str,
918
struct list_head *head,
@@ -914,6 +941,8 @@ static int process_input_file(FILE *outfile,
941
if (separator_pos >= 1) {
942
parse_trailer(&tok, &val, NULL, trailer,
943
separator_pos);
944
+ if (opts->unfold)
945
+ unfold_value(&val);
946
add_trailer_item(head,
947
strbuf_detach(&tok, NULL),
948
strbuf_detach(&val, NULL));
trailer.h
+1
@@ -27,6 +27,7 @@ struct process_trailer_options {
27
int trim_empty;
28
int only_trailers;
29
int only_input;
30
+ int unfold;
31
};
32
33
#define PROCESS_TRAILER_OPTIONS_INIT {0}