]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pretty format %(trailers): add a "keyonly"
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Wed, 9 Dec 2020 15:52:07 +0000 (16:52 +0100)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Dec 2020 22:16:42 +0000 (14:16 -0800)
Add support for a "keyonly". This allows for easier parsing out of the
key and value. Before if you didn't want to make assumptions about how
the key was formatted. You'd need to parse it out as e.g.:

    --pretty=format:'%H%x00%(trailers:separator=%x00%x00)' \
                       '%x00%(trailers:separator=%x00%x00,valueonly)'

And then proceed to deduce keys by looking at those two and
subtracting the value plus the hardcoded ": " separator from the
non-valueonly %(trailers) line. Now it's possible to simply do:

    --pretty=format:'%H%x00%(trailers:separator=%x00%x00,keyonly)' \
                    '%x00%(trailers:separator=%x00%x00,valueonly)'

Which at least reduces it to a state machine where you get N keys and
correlate them with N values. Even better would be to have a way to
change the ": " delimiter to something easily machine-readable (a key
might contain ": " too). A follow-up change will add support for that.

I don't really have a use-case for just "keyonly" myself. I suppose it
would be useful in some cases as "key=*" matches case-insensitively,
so a plain "keyonly" will give you the variants of the keys you
matched. I'm mainly adding it to fix the inconsistency with
"valueonly".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/pretty-formats.txt
pretty.c
t/t4205-log-pretty-formats.sh
trailer.c
trailer.h

index 973b6c7d482f5a1f4a827276d280ca015f3b0399..5eac36500d4685294cc270d77b849ffac387dfdd 100644 (file)
@@ -282,8 +282,8 @@ option is given with no value, it's enabled.
 ** 'unfold[=<BOOL>]': make it behave as if interpret-trailer's `--unfold`
    option was given. E.g.,
    `%(trailers:only,unfold=true)` unfolds and shows all trailer lines.
-** 'valueonly[=<BOOL>]': skip over the key part of the trailer line and only
-   show the value part.
+** 'keyonly[=<BOOL>]': only show the key part of the trailer.
+** 'valueonly[=<BOOL>]': only show the value part of the trailer.
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
index 7a7708a0ea707ac58f1961a65b40fa89ea8631d3..1237ee0e45d27ca326b8e03cf0e4652d7168f46c 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1451,6 +1451,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                                        opts.separator = &sepbuf;
                                } else if (!match_placeholder_bool_arg(arg, "only", &arg, &opts.only_trailers) &&
                                           !match_placeholder_bool_arg(arg, "unfold", &arg, &opts.unfold) &&
+                                          !match_placeholder_bool_arg(arg, "keyonly", &arg, &opts.key_only) &&
                                           !match_placeholder_bool_arg(arg, "valueonly", &arg, &opts.value_only))
                                        break;
                        }
index cb09a13249e9474259c349493189c587d528860c..4c9f6eb7946fe272731ecd05497718aaa5324acf 100755 (executable)
@@ -715,6 +715,22 @@ test_expect_success '%(trailers:key) without value is error' '
        test_cmp expect actual
 '
 
+test_expect_success '%(trailers:keyonly) shows only keys' '
+       git log --no-walk --pretty="format:%(trailers:keyonly)" >actual &&
+       test_write_lines \
+               "Signed-off-by" \
+               "Acked-by" \
+               "[ v2 updated patch description ]" \
+               "Signed-off-by" >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '%(trailers:key=foo,keyonly) shows only key' '
+       git log --no-walk --pretty="format:%(trailers:key=Acked-by,keyonly)" >actual &&
+       echo "Acked-by" >expect &&
+       test_cmp expect actual
+'
+
 test_expect_success '%(trailers:key=foo,valueonly) shows only value' '
        git log --no-walk --pretty="format:%(trailers:key=Acked-by,valueonly)" >actual &&
        echo "A U Thor <author@example.com>" >expect &&
@@ -732,6 +748,12 @@ test_expect_success '%(trailers:valueonly) shows only values' '
        test_cmp expect actual
 '
 
+test_expect_success '%(trailers:key=foo,keyonly,valueonly) shows nothing' '
+       git log --no-walk --pretty="format:%(trailers:key=Acked-by,keyonly,valueonly)" >actual &&
+       echo >expect &&
+       test_cmp expect actual
+'
+
 test_expect_success 'pretty format %(trailers:separator) changes separator' '
        git log --no-walk --pretty=format:"X%(trailers:separator=%x00)X" >actual &&
        (
@@ -754,7 +776,7 @@ test_expect_success 'pretty format %(trailers:separator=X,unfold) changes separa
        test_cmp expect actual
 '
 
-test_expect_success 'pretty format %(trailers) combining separator/key/valueonly' '
+test_expect_success 'pretty format %(trailers) combining separator/key/keyonly/valueonly' '
        git commit --allow-empty -F - <<-\EOF &&
        Important fix
 
@@ -781,6 +803,13 @@ test_expect_success 'pretty format %(trailers) combining separator/key/valueonly
                "Does not close any tickets" \
                "Another fix #567, #890" \
                "Important fix #1234" >expect &&
+       test_cmp expect actual &&
+
+       git log --pretty="%s% (trailers:separator=%x2c%x20,key=Closes,keyonly)" HEAD~3.. >actual &&
+       test_write_lines \
+               "Does not close any tickets" \
+               "Another fix Closes, Closes" \
+               "Important fix Closes" >expect &&
        test_cmp expect actual
 '
 
index d2d01015b1dd92c3e486fe7f7e99418320f8c90d..889b419a4f6fac85f372be0805400a42db28cfbc 100644 (file)
--- a/trailer.c
+++ b/trailer.c
@@ -1132,7 +1132,7 @@ static void format_trailer_info(struct strbuf *out,
 
        /* If we want the whole block untouched, we can take the fast path. */
        if (!opts->only_trailers && !opts->unfold && !opts->filter &&
-           !opts->separator && !opts->value_only) {
+           !opts->separator && !opts->key_only && !opts->value_only) {
                strbuf_add(out, info->trailer_start,
                           info->trailer_end - info->trailer_start);
                return;
@@ -1154,8 +1154,11 @@ static void format_trailer_info(struct strbuf *out,
                                if (opts->separator && out->len != origlen)
                                        strbuf_addbuf(out, opts->separator);
                                if (!opts->value_only)
-                                       strbuf_addf(out, "%s: ", tok.buf);
-                               strbuf_addbuf(out, &val);
+                                       strbuf_addbuf(out, &tok);
+                               if (!opts->key_only && !opts->value_only)
+                                       strbuf_addstr(out, ": ");
+                               if (!opts->key_only)
+                                       strbuf_addbuf(out, &val);
                                if (!opts->separator)
                                        strbuf_addch(out, '\n');
                        }
index cd93e7ddea789cb6c320af2a7b984bd6f8a8215f..d2f28776be6f63d81f155d34b8b0f2ba6bcd39a4 100644 (file)
--- a/trailer.h
+++ b/trailer.h
@@ -71,6 +71,7 @@ struct process_trailer_options {
        int only_input;
        int unfold;
        int no_divider;
+       int key_only;
        int value_only;
        const struct strbuf *separator;
        int (*filter)(const struct strbuf *, void *);