Junio C Hamano [off-list ref] writes:
One issue %w() sidesteps is handing of single liner commit log messages
(this is not a new issue your %B(n) introduces). "%s%n%b" will give us
the original message only when the log has some contents in addition to
the single-line summary. Otherwise we will get an extra blank line.
Perhaps we could extend the pretty-printer so that it understands %+x
notation, which expands to %n%x when %x expands to a non-empty result, and
otherwise it expands to empty, as a generic extension applicable to any
format specifier 'x'. If we have such a notation, "%s%+b", would be a
reasonable way to say "give us the original commit log message here", and
we won't need %w(i,j,w) -- we can instead say %S(i,j,w)%+B(i,j,w), or
%s%+B(i,j,w) depending on what you want.
This teaches the machinery to add a separator LF before any non-empty
expansion of '%x' if you ask '%+x', and also removes LF if '%x' expands to
an empty string if you ask '%-x', for any supported expansion placeholder
'x' it supports.
With the first two patches Dscho posted (and then polished in his tree),
it shouldn't be too hard to update your %B(n) to %B(i,j,w) and also add
%S(i,j,w) in a similar way, to allow people to say %S(i,j,w)%+B(i,j,w)
instead of (or in addition to) his %w(i,j,w).
pretty.c | 42 ++++++++++++++++++++++++++++++++++++++++--
t/t6006-rev-list-format.sh | 22 ++++++++++++++++++++++
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/pretty.c b/pretty.c
index f5983f8..081feb6 100644
--- a/pretty.c
+++ b/pretty.c
@@ -595,8 +595,8 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
strbuf_addch(sb, ')');
}
-static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
- void *context)
+static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
+ void *context)
{
struct format_commit_context *c = context;
const struct commit *commit = c->commit;@@ -739,6 +739,44 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
return 0; /* unknown placeholder */
}
+static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
+ void *context)
+{
+ int consumed;
+ size_t orig_len;
+ enum {
+ NO_MAGIC,
+ ADD_LF_BEFORE_NON_EMPTY,
+ DEL_LF_BEFORE_EMPTY,
+ } magic = NO_MAGIC;
+
+ switch (placeholder[0]) {
+ case '-':
+ magic = DEL_LF_BEFORE_EMPTY;
+ break;
+ case '+':
+ magic = ADD_LF_BEFORE_NON_EMPTY;
+ break;
+ default:
+ break;
+ }
+ if (magic != NO_MAGIC)
+ placeholder++;
+
+ orig_len = sb->len;
+ consumed = format_commit_one(sb, placeholder, context);
+ if (magic == NO_MAGIC)
+ return consumed;
+
+ if ((orig_len == sb->len) && magic == DEL_LF_BEFORE_EMPTY) {
+ while (sb->len && sb->buf[sb->len - 1] == '\n')
+ strbuf_setlen(sb, sb->len - 1);
+ } else if ((orig_len != sb->len) && magic == ADD_LF_BEFORE_NON_EMPTY) {
+ strbuf_insert(sb, orig_len, "\n", 1);
+ }
+ return consumed + 1;
+}
+
void format_commit_message(const struct commit *commit,
const void *format, struct strbuf *sb,
enum date_mode dmode)diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 59d1f62..18a77a7 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -162,4 +162,26 @@ test_expect_success 'empty email' '
}
'
+test_expect_success 'del LF before empty (1)' '
+ git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual &&
+ test $(wc -l <actual) = 2
+'
+
+test_expect_success 'del LF before empty (2)' '
+ git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD >actual &&
+ test $(wc -l <actual) = 6 &&
+ grep "^$" actual
+'
+
+test_expect_success 'add LF before non-empty (1)' '
+ git show -s --pretty=format:"%s%+b%nThanks%n" HEAD^^ >actual &&
+ test $(wc -l <actual) = 2
+'
+
+test_expect_success 'add LF before non-empty (2)' '
+ git show -s --pretty=format:"%s%+b%nThanks%n" HEAD >actual &&
+ test $(wc -l <actual) = 6 &&
+ grep "^$" actual
+'
+
test_done
.