ref-filter: add support to display trailers as part of contents

Add %(trailers) and %(contents:trailers) to display the trailers as interpreted by trailer_info_get. Update documentation and add a test for the new feature. Signed-off-by: Jacob Keller <jacob.keller@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jacob Keller committed Nov 18, 2016 at 16:58 UTC b1d31c8954f9c21b275f4fb7d872414b564c201c
3 files changed +49 -1
Documentation/git-for-each-ref.txt
+2
@@ -165,6 +165,8 @@ of all lines of the commit message up to the first blank line. The next
165 line is 'contents:body', where body is all of the lines after the first
166 blank line. The optional GPG signature is `contents:signature`. The
167 first `N` lines of the message is obtained using `contents:lines=N`.
168 +Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
169 +are obtained as 'contents:trailers'.
170
171 For sorting purposes, fields with numeric values sort in numeric order
172 (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).
ref-filter.c
+21 -1
@@ -13,6 +13,7 @@
13 #include "utf8.h"
14 #include "git-compat-util.h"
15 #include "version.h"
16 +#include "trailer.h"
17
18 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
19
@@ -40,7 +41,7 @@ static struct used_atom {
41 enum { RR_NORMAL, RR_SHORTEN, RR_TRACK, RR_TRACKSHORT }
42 remote_ref;
43 struct {
43 - enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB } option;
44 + enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option;
45 unsigned int nlines;
46 } contents;
47 enum { O_FULL, O_SHORT } objectname;
@@ -85,6 +86,13 @@ static void subject_atom_parser(struct used_atom *atom, const char *arg)
86 atom->u.contents.option = C_SUB;
87 }
88
89 +static void trailers_atom_parser(struct used_atom *atom, const char *arg)
90 +{
91 + if (arg)
92 + die(_("%%(trailers) does not take arguments"));
93 + atom->u.contents.option = C_TRAILERS;
94 +}
95 +
96 static void contents_atom_parser(struct used_atom *atom, const char *arg)
97 {
98 if (!arg)
@@ -95,6 +103,8 @@ static void contents_atom_parser(struct used_atom *atom, const char *arg)
103 atom->u.contents.option = C_SIG;
104 else if (!strcmp(arg, "subject"))
105 atom->u.contents.option = C_SUB;
106 + else if (!strcmp(arg, "trailers"))
107 + atom->u.contents.option = C_TRAILERS;
108 else if (skip_prefix(arg, "lines=", &arg)) {
109 atom->u.contents.option = C_LINES;
110 if (strtoul_ui(arg, 10, &atom->u.contents.nlines))
@@ -194,6 +204,7 @@ static struct {
204 { "creatordate", FIELD_TIME },
205 { "subject", FIELD_STR, subject_atom_parser },
206 { "body", FIELD_STR, body_atom_parser },
207 + { "trailers", FIELD_STR, trailers_atom_parser },
208 { "contents", FIELD_STR, contents_atom_parser },
209 { "upstream", FIELD_STR, remote_ref_atom_parser },
210 { "push", FIELD_STR, remote_ref_atom_parser },
@@ -785,6 +796,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
796 name++;
797 if (strcmp(name, "subject") &&
798 strcmp(name, "body") &&
799 + strcmp(name, "trailers") &&
800 !starts_with(name, "contents"))
801 continue;
802 if (!subpos)
@@ -808,6 +820,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
820 /* Size is the length of the message after removing the signature */
821 append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines);
822 v->s = strbuf_detach(&s, NULL);
823 + } else if (atom->u.contents.option == C_TRAILERS) {
824 + struct trailer_info info;
825 +
826 + /* Search for trailer info */
827 + trailer_info_get(&info, subpos);
828 + v->s = xmemdupz(info.trailer_start,
829 + info.trailer_end - info.trailer_start);
830 + trailer_info_release(&info);
831 } else if (atom->u.contents.option == C_BARE)
832 v->s = xstrdup(subpos);
833 }
t/t6300-for-each-ref.sh
+26
@@ -553,4 +553,30 @@ test_expect_success 'Verify sort with multiple keys' '
553 refs/tags/bogo refs/tags/master > actual &&
554 test_cmp expected actual
555 '
556 +
557 +cat >trailers <<EOF
558 +Reviewed-by: A U Thor <author@example.com>
559 +Signed-off-by: A U Thor <author@example.com>
560 +EOF
561 +
562 +test_expect_success 'basic atom: head contents:trailers' '
563 + echo "Some contents" > two &&
564 + git add two &&
565 + git commit -F - <<-EOF &&
566 + trailers: this commit message has trailers
567 +
568 + Some message contents
569 +
570 + $(cat trailers)
571 + EOF
572 + git for-each-ref --format="%(contents:trailers)" refs/heads/master >actual &&
573 + sanitize_pgp <actual >actual.clean &&
574 + # git for-each-ref ends with a blank line
575 + cat >expect <<-EOF &&
576 + $(cat trailers)
577 +
578 + EOF
579 + test_cmp expect actual.clean
580 +'
581 +
582 test_done