|
|
|
@ -181,6 +181,20 @@ static int is_empty_line(const char *line, int *len_p)
@@ -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) |
|
|
|
|
{ |
|
|
|
@ -410,13 +424,15 @@ struct chunk {
@@ -410,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. */ |
|
|
|
@ -446,23 +462,14 @@ static void parse_commit_header(struct format_commit_context *context)
@@ -446,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; |
|
|
|
@ -474,13 +481,50 @@ static void parse_commit_header(struct format_commit_context *context)
@@ -474,13 +481,50 @@ 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
if (!sb) |
|
|
|
|
continue; |
|
|
|
|
strbuf_grow(sb, linelen + 2); |
|
|
|
|
if (!first) |
|
|
|
|
strbuf_addstr(sb, line_separator); |
|
|
|
|
strbuf_add(sb, line, linelen); |
|
|
|
|
first = 0; |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
@ -600,9 +644,6 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
@@ -600,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, |
|
|
|
@ -614,6 +655,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
@@ -614,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; |
|
|
|
@ -704,27 +755,11 @@ void pp_title_line(enum cmit_fmt fmt,
@@ -704,27 +755,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) { |
|
|
|
@ -850,15 +885,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
@@ -850,15 +885,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) |
|
|
|
|