From 80583c0ef61cc966c7eee79cf3623a83197e19b8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Jun 2007 00:34:54 -0700 Subject: Lift 16kB limit of log message output Traditionally we had 16kB limit when formatting log messages for output, because it was easier to arrange for the caller to have a reasonably big buffer and pass it down without ever worrying about reallocating. This changes the calling convention of pretty_print_commit() to lift this limit. Instead of the buffer and remaining length, it now takes a pointer to the pointer that points at the allocated buffer, and another pointer to the location that stores the allocated length, and reallocates the buffer as necessary. To support the user format, the error return of interpolate() needed to be changed. It used to return a bool telling "Ok the result fits", or "Sorry, I had to truncate it". Now it returns 0 on success, and returns the size of the buffer it wants in order to fit the whole result. Signed-off-by: Junio C Hamano --- commit.c | 55 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index 4ca4d44ba..d43a68ecb 100644 --- a/commit.c +++ b/commit.c @@ -776,7 +776,7 @@ static void fill_person(struct interp *table, const char *msg, int len) } static long format_commit_message(const struct commit *commit, - const char *msg, char *buf, unsigned long space) + const char *msg, char **buf_p, unsigned long *space_p) { struct interp table[] = { { "%H" }, /* commit hash */ @@ -905,16 +905,27 @@ static long format_commit_message(const struct commit *commit, if (!table[i].value) interp_set_entry(table, i, ""); - interpolate(buf, space, user_format, table, ARRAY_SIZE(table)); + do { + char *buf = *buf_p; + unsigned long space = *space_p; + + space = interpolate(buf, space, user_format, + table, ARRAY_SIZE(table)); + if (!space) + break; + buf = xrealloc(buf, space); + *buf_p = buf; + *space_p = space; + } while (1); interp_clear_table(table, ARRAY_SIZE(table)); - return strlen(buf); + return strlen(*buf_p); } unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, - char *buf, unsigned long space, + char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode) @@ -927,9 +938,11 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, int plain_non_ascii = 0; char *reencoded; const char *encoding; + char *buf; + unsigned long space, slop; if (fmt == CMIT_FMT_USERFORMAT) - return format_commit_message(commit, msg, buf, space); + return format_commit_message(commit, msg, buf_p, space_p); encoding = (git_log_output_encoding ? git_log_output_encoding @@ -969,6 +982,26 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, } } + space = *space_p; + buf = *buf_p; + + /* + * We do not want to repeatedly realloc below, so + * preallocate with enough slop to hold MIME headers, + * "Subject: " prefix, etc. + */ + slop = 1000; + if (subject) + slop += strlen(subject); + if (after_subject) + slop += strlen(after_subject); + if (space < strlen(msg) + slop) { + space = strlen(msg) + slop; + buf = xrealloc(buf, space); + *space_p = space; + *buf_p = buf; + } + for (;;) { const char *line = msg; int linelen = get_one_line(msg, len); @@ -976,14 +1009,12 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, if (!linelen) break; - /* - * We want some slop for indentation and a possible - * final "...". Thus the "+ 20". - */ + /* 20 would cover indent and leave us some slop */ if (offset + linelen + 20 > space) { - memcpy(buf + offset, " ...\n", 8); - offset += 8; - break; + space = offset + linelen + 20; + buf = xrealloc(buf, space); + *buf_p = buf; + *space_p = space; } msg += linelen; -- cgit v1.2.1