ref-filter: use pretty.c logic for trailers

Now, ref-filter is using pretty.c logic for setting trailer options. New to ref-filter: :key=<K> - only show trailers with specified key. :valueonly[=val] - only show the value part. :separator=<SEP> - inserted between trailer lines. :key_value_separator=<SEP> - inserted between key and value in trailer lines Enhancement to existing options(now can take value and its optional): :only[=val] :unfold[=val] 'val' can be: true, on, yes or false, off, no. Mentored-by: Christian Couder <chriscool@tuxfamily.org> Mentored-by: Heba Waly <heba.waly@gmail.com> Signed-off-by: Hariom Verma <hariom18599@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Hariom Verma committed Feb 13, 2021 at 01:52 UTC ee82a487f68a7c86551fb59f6176812d63be61b6
3 files changed +118 -21
Documentation/git-for-each-ref.txt
+3 -5
@@ -260,11 +260,9 @@ contents:lines=N::
260 The first `N` lines of the message.
261
262 Additionally, the trailers as interpreted by linkgit:git-interpret-trailers[1]
263 -are obtained as `trailers` (or by using the historical alias
264 -`contents:trailers`). Non-trailer lines from the trailer block can be omitted
265 -with `trailers:only`. Whitespace-continuations can be removed from trailers so
266 -that each trailer appears on a line by itself with its full content with
267 -`trailers:unfold`. Both can be used together as `trailers:unfold,only`.
263 +are obtained as `trailers[:options]` (or by using the historical alias
264 +`contents:trailers[:options]`). For valid [:option] values see `trailers`
265 +section of linkgit:git-log[1].
266
267 For sorting purposes, fields with numeric values sort in numeric order
268 (`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).
ref-filter.c
+20 -16
@@ -67,6 +67,12 @@ struct refname_atom {
67 int lstrip, rstrip;
68 };
69
70 +static struct ref_trailer_buf {
71 + struct string_list filter_list;
72 + struct strbuf sepbuf;
73 + struct strbuf kvsepbuf;
74 +} ref_trailer_buf = {STRING_LIST_INIT_NODUP, STRBUF_INIT, STRBUF_INIT};
75 +
76 static struct expand_data {
77 struct object_id oid;
78 enum object_type type;
@@ -313,28 +319,26 @@ static int subject_atom_parser(const struct ref_format *format, struct used_atom
319 static int trailers_atom_parser(const struct ref_format *format, struct used_atom *atom,
320 const char *arg, struct strbuf *err)
321 {
316 - struct string_list params = STRING_LIST_INIT_DUP;
317 - int i;
318 -
322 atom->u.contents.trailer_opts.no_divider = 1;
323
324 if (arg) {
322 - string_list_split(&params, arg, ',', -1);
323 - for (i = 0; i < params.nr; i++) {
324 - const char *s = params.items[i].string;
325 - if (!strcmp(s, "unfold"))
326 - atom->u.contents.trailer_opts.unfold = 1;
327 - else if (!strcmp(s, "only"))
328 - atom->u.contents.trailer_opts.only_trailers = 1;
329 - else {
330 - strbuf_addf(err, _("unknown %%(trailers) argument: %s"), s);
331 - string_list_clear(&params, 0);
332 - return -1;
333 - }
325 + const char *argbuf = xstrfmt("%s)", arg);
326 + char *invalid_arg = NULL;
327 +
328 + if (format_set_trailers_options(&atom->u.contents.trailer_opts,
329 + &ref_trailer_buf.filter_list,
330 + &ref_trailer_buf.sepbuf,
331 + &ref_trailer_buf.kvsepbuf,
332 + &argbuf, &invalid_arg)) {
333 + if (!invalid_arg)
334 + strbuf_addf(err, _("expected %%(trailers:key=<value>)"));
335 + else
336 + strbuf_addf(err, _("unknown %%(trailers) argument: %s"), invalid_arg);
337 + free((char *)invalid_arg);
338 + return -1;
339 }
340 }
341 atom->u.contents.option = C_TRAILERS;
337 - string_list_clear(&params, 0);
342 return 0;
343 }
344
t/t6300-for-each-ref.sh
+95
@@ -837,6 +837,24 @@ test_trailer_option '%(trailers:only) shows only "key: value" trailers' \
837
838 EOF
839
840 +test_trailer_option '%(trailers:only=no,only=true) shows only "key: value" trailers' \
841 + 'trailers:only=no,only=true' <<-EOF
842 + $(grep -v patch.description <trailers)
843 +
844 + EOF
845 +
846 +test_trailer_option '%(trailers:only=yes) shows only "key: value" trailers' \
847 + 'trailers:only=yes' <<-EOF
848 + $(grep -v patch.description <trailers)
849 +
850 + EOF
851 +
852 +test_trailer_option '%(trailers:only=no) shows all trailers' \
853 + 'trailers:only=no' <<-EOF
854 + $(cat trailers)
855 +
856 + EOF
857 +
858 test_trailer_option '%(trailers:only) and %(trailers:unfold) work together' \
859 'trailers:only,unfold' <<-EOF
860 $(grep -v patch.description <trailers | unfold)
@@ -849,6 +867,78 @@ test_trailer_option '%(trailers:unfold) and %(trailers:only) work together' \
867
868 EOF
869
870 +test_trailer_option '%(trailers:key=foo) shows that trailer' \
871 + 'trailers:key=Signed-off-by' <<-EOF
872 + Signed-off-by: A U Thor <author@example.com>
873 +
874 + EOF
875 +
876 +test_trailer_option '%(trailers:key=foo) is case insensitive' \
877 + 'trailers:key=SiGned-oFf-bY' <<-EOF
878 + Signed-off-by: A U Thor <author@example.com>
879 +
880 + EOF
881 +
882 +test_trailer_option '%(trailers:key=foo:) trailing colon also works' \
883 + 'trailers:key=Signed-off-by:' <<-EOF
884 + Signed-off-by: A U Thor <author@example.com>
885 +
886 + EOF
887 +
888 +test_trailer_option '%(trailers:key=foo) multiple keys' \
889 + 'trailers:key=Reviewed-by:,key=Signed-off-by' <<-EOF
890 + Reviewed-by: A U Thor <author@example.com>
891 + Signed-off-by: A U Thor <author@example.com>
892 +
893 + EOF
894 +
895 +test_trailer_option '%(trailers:key=nonexistent) becomes empty' \
896 + 'trailers:key=Shined-off-by:' <<-EOF
897 +
898 + EOF
899 +
900 +test_trailer_option '%(trailers:key=foo) handles multiple lines even if folded' \
901 + 'trailers:key=Acked-by' <<-EOF
902 + $(grep -v patch.description <trailers | grep -v Signed-off-by | grep -v Reviewed-by)
903 +
904 + EOF
905 +
906 +test_trailer_option '%(trailers:key=foo,unfold) properly unfolds' \
907 + 'trailers:key=Signed-Off-by,unfold' <<-EOF
908 + $(unfold <trailers | grep Signed-off-by)
909 +
910 + EOF
911 +
912 +test_trailer_option '%(trailers:key=foo,only=no) also includes nontrailer lines' \
913 + 'trailers:key=Signed-off-by,only=no' <<-EOF
914 + Signed-off-by: A U Thor <author@example.com>
915 + $(grep patch.description <trailers)
916 +
917 + EOF
918 +
919 +test_trailer_option '%(trailers:key=foo,valueonly) shows only value' \
920 + 'trailers:key=Signed-off-by,valueonly' <<-EOF
921 + A U Thor <author@example.com>
922 +
923 + EOF
924 +
925 +test_trailer_option '%(trailers:separator) changes separator' \
926 + 'trailers:separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
927 + Reviewed-by: A U Thor <author@example.com>,Signed-off-by: A U Thor <author@example.com>
928 + EOF
929 +
930 +test_trailer_option '%(trailers:key_value_separator) changes key-value separator' \
931 + 'trailers:key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
932 + Reviewed-by,A U Thor <author@example.com>
933 + Signed-off-by,A U Thor <author@example.com>
934 +
935 + EOF
936 +
937 +test_trailer_option '%(trailers:separator,key_value_separator) changes both separators' \
938 + 'trailers:separator=%x2C,key_value_separator=%x2C,key=Reviewed-by,key=Signed-off-by:' <<-EOF
939 + Reviewed-by,A U Thor <author@example.com>,Signed-off-by,A U Thor <author@example.com>
940 + EOF
941 +
942 test_failing_trailer_option () {
943 title=$1 option=$2
944 cat >expect
@@ -866,6 +956,11 @@ test_failing_trailer_option '%(trailers) rejects unknown trailers arguments' \
956 fatal: unknown %(trailers) argument: unsupported
957 EOF
958
959 +test_failing_trailer_option '%(trailers:key) without value is error' \
960 + 'trailers:key' <<-\EOF
961 + fatal: expected %(trailers:key=<value>)
962 + EOF
963 +
964 test_expect_success 'if arguments, %(contents:trailers) shows error if colon is missing' '
965 cat >expect <<-EOF &&
966 fatal: unrecognized %(contents) argument: trailersonly