From a010966844221ea14f1de26fdab8fe37332ff928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:32:49 +0100 Subject: pretty: factor out skip_empty_lines() The patch after the next one will use it. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pretty.c b/pretty.c index f6ff31264..c43497bb2 100644 --- a/pretty.c +++ b/pretty.c @@ -181,6 +181,20 @@ static int is_empty_line(const char *line, int *len_p) return !len; } +static const char *skip_empty_lines(const char *msg) +{ + for (;;) { + int linelen = get_one_line(msg); + int ll = linelen; + if (!linelen) + break; + if (!is_empty_line(msg, &ll)) + break; + msg += linelen; + } + return msg; +} + static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, const struct commit *commit, int abbrev) { @@ -850,15 +864,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, } /* Skip excess blank lines at the beginning of body, if any... */ - for (;;) { - int linelen = get_one_line(msg); - int ll = linelen; - if (!linelen) - break; - if (!is_empty_line(msg, &ll)) - break; - msg += linelen; - } + msg = skip_empty_lines(msg); /* These formats treat the title line specially. */ if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) -- cgit v1.2.1 From 88c44735ab24aea3e669501c4491f7c9ca745ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:39:35 +0100 Subject: pretty: factor out format_subject() The next patch will use it. In the version that was factored out, we can't rely on the len of the struct strbuf to find out if a line separator needs to be added, as it might already contain something. Add a guard variable ("first") instead. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/pretty.c b/pretty.c index c43497bb2..632abc523 100644 --- a/pretty.c +++ b/pretty.c @@ -495,6 +495,28 @@ static void parse_commit_header(struct format_commit_context *context) context->commit_header_parsed = 1; } +static const char *format_subject(struct strbuf *sb, const char *msg, + const char *line_separator) +{ + int first = 1; + + for (;;) { + const char *line = msg; + int linelen = get_one_line(line); + + msg += linelen; + if (!linelen || is_empty_line(line, &linelen)) + break; + + strbuf_grow(sb, linelen + 2); + if (!first) + strbuf_addstr(sb, line_separator); + strbuf_add(sb, line, linelen); + first = 0; + } + return msg; +} + static void format_decoration(struct strbuf *sb, const struct commit *commit) { struct name_decoration *d; @@ -718,27 +740,11 @@ void pp_title_line(enum cmit_fmt fmt, const char *encoding, int need_8bit_cte) { + const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " "; struct strbuf title; strbuf_init(&title, 80); - - for (;;) { - const char *line = *msg_p; - int linelen = get_one_line(line); - - *msg_p += linelen; - if (!linelen || is_empty_line(line, &linelen)) - break; - - strbuf_grow(&title, linelen + 2); - if (title.len) { - if (fmt == CMIT_FMT_EMAIL) { - strbuf_addch(&title, '\n'); - } - strbuf_addch(&title, ' '); - } - strbuf_add(&title, line, linelen); - } + *msg_p = format_subject(&title, *msg_p, line_separator); strbuf_grow(sb, title.len + 1024); if (subject) { -- cgit v1.2.1 From f53bd743ff713f6507f28f8e730ac3e27858ab43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:49:21 +0100 Subject: pretty: support multiline subjects with format: git log --pretty=format:%s (and tformat:) used to display the first line of the subject, unlike the other --pretty options, which would construct a subject line from all lines of the first paragraph of the commit message. For consistency and increased code reuse, change format: to do the same as the other options. Before: $ git log --pretty=oneline v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - $ git log --pretty=tformat:"%H %s" v1.6.1 | md5sum 298903b1c065002e15daa5329213c51f - After: $ git log --pretty=tformat:"%H %s" v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - $ git log --pretty=oneline v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/pretty.c b/pretty.c index 632abc523..343dca556 100644 --- a/pretty.c +++ b/pretty.c @@ -424,13 +424,15 @@ struct chunk { struct format_commit_context { const struct commit *commit; enum date_mode dmode; + unsigned commit_header_parsed:1; + unsigned commit_message_parsed:1; /* These offsets are relative to the start of the commit message. */ - int commit_header_parsed; - struct chunk subject; struct chunk author; struct chunk committer; struct chunk encoding; + size_t message_off; + size_t subject_off; size_t body_off; /* The following ones are relative to the result struct strbuf. */ @@ -460,23 +462,14 @@ static void parse_commit_header(struct format_commit_context *context) { const char *msg = context->commit->buffer; int i; - enum { HEADER, SUBJECT, BODY } state; - for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { + for (i = 0; msg[i]; i++) { int eol; for (eol = i; msg[eol] && msg[eol] != '\n'; eol++) ; /* do nothing */ - if (state == SUBJECT) { - context->subject.off = i; - context->subject.len = eol - i; - i = eol; - } if (i == eol) { - state++; - /* strip empty lines */ - while (msg[eol] == '\n' && msg[eol + 1] == '\n') - eol++; + break; } else if (!prefixcmp(msg + i, "author ")) { context->author.off = i + 7; context->author.len = eol - i - 7; @@ -488,10 +481,8 @@ static void parse_commit_header(struct format_commit_context *context) context->encoding.len = eol - i - 9; } i = eol; - if (!msg[i]) - break; } - context->body_off = i; + context->message_off = i; context->commit_header_parsed = 1; } @@ -508,6 +499,8 @@ static const char *format_subject(struct strbuf *sb, const char *msg, if (!linelen || is_empty_line(line, &linelen)) break; + if (!sb) + continue; strbuf_grow(sb, linelen + 2); if (!first) strbuf_addstr(sb, line_separator); @@ -517,6 +510,21 @@ static const char *format_subject(struct strbuf *sb, const char *msg, return msg; } +static void parse_commit_message(struct format_commit_context *c) +{ + const char *msg = c->commit->buffer + c->message_off; + const char *start = c->commit->buffer; + + msg = skip_empty_lines(msg); + c->subject_off = msg - start; + + msg = format_subject(NULL, msg, NULL); + msg = skip_empty_lines(msg); + c->body_off = msg - start; + + c->commit_message_parsed = 1; +} + static void format_decoration(struct strbuf *sb, const struct commit *commit) { struct name_decoration *d; @@ -636,9 +644,6 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, parse_commit_header(c); switch (placeholder[0]) { - case 's': /* subject */ - strbuf_add(sb, msg + c->subject.off, c->subject.len); - return 1; case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, @@ -650,6 +655,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, case 'e': /* encoding */ strbuf_add(sb, msg + c->encoding.off, c->encoding.len); return 1; + } + + /* Now we need to parse the commit message. */ + if (!c->commit_message_parsed) + parse_commit_message(c); + + switch (placeholder[0]) { + case 's': /* subject */ + format_subject(sb, msg + c->subject_off, " "); + return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; -- cgit v1.2.1