Skip to content

Commit a9012e3

Browse files
committed
Merge branch 'rs/maint-tformat-foldline' into maint
* rs/maint-tformat-foldline: pretty: support multiline subjects with format: pretty: factor out format_subject() pretty: factor out skip_empty_lines()
2 parents f611c8c + f53bd74 commit a9012e3

File tree

1 file changed

+73
-46
lines changed

1 file changed

+73
-46
lines changed

pretty.c

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,20 @@ static int is_empty_line(const char *line, int *len_p)
181181
return !len;
182182
}
183183

184+
static const char *skip_empty_lines(const char *msg)
185+
{
186+
for (;;) {
187+
int linelen = get_one_line(msg);
188+
int ll = linelen;
189+
if (!linelen)
190+
break;
191+
if (!is_empty_line(msg, &ll))
192+
break;
193+
msg += linelen;
194+
}
195+
return msg;
196+
}
197+
184198
static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,
185199
const struct commit *commit, int abbrev)
186200
{
@@ -410,13 +424,15 @@ struct chunk {
410424
struct format_commit_context {
411425
const struct commit *commit;
412426
enum date_mode dmode;
427+
unsigned commit_header_parsed:1;
428+
unsigned commit_message_parsed:1;
413429

414430
/* These offsets are relative to the start of the commit message. */
415-
int commit_header_parsed;
416-
struct chunk subject;
417431
struct chunk author;
418432
struct chunk committer;
419433
struct chunk encoding;
434+
size_t message_off;
435+
size_t subject_off;
420436
size_t body_off;
421437

422438
/* The following ones are relative to the result struct strbuf. */
@@ -446,23 +462,14 @@ static void parse_commit_header(struct format_commit_context *context)
446462
{
447463
const char *msg = context->commit->buffer;
448464
int i;
449-
enum { HEADER, SUBJECT, BODY } state;
450465

451-
for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
466+
for (i = 0; msg[i]; i++) {
452467
int eol;
453468
for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
454469
; /* do nothing */
455470

456-
if (state == SUBJECT) {
457-
context->subject.off = i;
458-
context->subject.len = eol - i;
459-
i = eol;
460-
}
461471
if (i == eol) {
462-
state++;
463-
/* strip empty lines */
464-
while (msg[eol] == '\n' && msg[eol + 1] == '\n')
465-
eol++;
472+
break;
466473
} else if (!prefixcmp(msg + i, "author ")) {
467474
context->author.off = i + 7;
468475
context->author.len = eol - i - 7;
@@ -474,13 +481,50 @@ static void parse_commit_header(struct format_commit_context *context)
474481
context->encoding.len = eol - i - 9;
475482
}
476483
i = eol;
477-
if (!msg[i])
478-
break;
479484
}
480-
context->body_off = i;
485+
context->message_off = i;
481486
context->commit_header_parsed = 1;
482487
}
483488

489+
static const char *format_subject(struct strbuf *sb, const char *msg,
490+
const char *line_separator)
491+
{
492+
int first = 1;
493+
494+
for (;;) {
495+
const char *line = msg;
496+
int linelen = get_one_line(line);
497+
498+
msg += linelen;
499+
if (!linelen || is_empty_line(line, &linelen))
500+
break;
501+
502+
if (!sb)
503+
continue;
504+
strbuf_grow(sb, linelen + 2);
505+
if (!first)
506+
strbuf_addstr(sb, line_separator);
507+
strbuf_add(sb, line, linelen);
508+
first = 0;
509+
}
510+
return msg;
511+
}
512+
513+
static void parse_commit_message(struct format_commit_context *c)
514+
{
515+
const char *msg = c->commit->buffer + c->message_off;
516+
const char *start = c->commit->buffer;
517+
518+
msg = skip_empty_lines(msg);
519+
c->subject_off = msg - start;
520+
521+
msg = format_subject(NULL, msg, NULL);
522+
msg = skip_empty_lines(msg);
523+
c->body_off = msg - start;
524+
525+
c->commit_message_parsed = 1;
526+
}
527+
484528
static void format_decoration(struct strbuf *sb, const struct commit *commit)
485529
{
486530
struct name_decoration *d;
@@ -600,9 +644,6 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
600644
parse_commit_header(c);
601645

602646
switch (placeholder[0]) {
603-
case 's': /* subject */
604-
strbuf_add(sb, msg + c->subject.off, c->subject.len);
605-
return 1;
606647
case 'a': /* author ... */
607648
return format_person_part(sb, placeholder[1],
608649
msg + c->author.off, c->author.len,
@@ -614,6 +655,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
614655
case 'e': /* encoding */
615656
strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
616657
return 1;
658+
}
659+
660+
/* Now we need to parse the commit message. */
661+
if (!c->commit_message_parsed)
662+
parse_commit_message(c);
663+
664+
switch (placeholder[0]) {
665+
case 's': /* subject */
666+
format_subject(sb, msg + c->subject_off, " ");
667+
return 1;
617668
case 'b': /* body */
618669
strbuf_addstr(sb, msg + c->body_off);
619670
return 1;
@@ -704,27 +755,11 @@ void pp_title_line(enum cmit_fmt fmt,
704755
const char *encoding,
705756
int need_8bit_cte)
706757
{
758+
const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
707759
struct strbuf title;
708760

709761
strbuf_init(&title, 80);
710-
711-
for (;;) {
712-
const char *line = *msg_p;
713-
int linelen = get_one_line(line);
714-
715-
*msg_p += linelen;
716-
if (!linelen || is_empty_line(line, &linelen))
717-
break;
718-
719-
strbuf_grow(&title, linelen + 2);
720-
if (title.len) {
721-
if (fmt == CMIT_FMT_EMAIL) {
722-
strbuf_addch(&title, '\n');
723-
}
724-
strbuf_addch(&title, ' ');
725-
}
726-
strbuf_add(&title, line, linelen);
727-
}
762+
*msg_p = format_subject(&title, *msg_p, line_separator);
728763

729764
strbuf_grow(sb, title.len + 1024);
730765
if (subject) {
@@ -850,15 +885,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
850885
}
851886

852887
/* Skip excess blank lines at the beginning of body, if any... */
853-
for (;;) {
854-
int linelen = get_one_line(msg);
855-
int ll = linelen;
856-
if (!linelen)
857-
break;
858-
if (!is_empty_line(msg, &ll))
859-
break;
860-
msg += linelen;
861-
}
888+
msg = skip_empty_lines(msg);
862889

863890
/* These formats treat the title line specially. */
864891
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)

0 commit comments

Comments
 (0)