diff options
Diffstat (limited to 'commit.c')
-rw-r--r-- | commit.c | 333 |
1 files changed, 124 insertions, 209 deletions
@@ -458,11 +458,11 @@ void clear_commit_marks(struct commit *commit, unsigned int mark) /* * Generic support for pretty-printing the header */ -static int get_one_line(const char *msg, unsigned long len) +static int get_one_line(const char *msg) { int ret = 0; - while (len--) { + for (;;) { char c = *msg++; if (!c) break; @@ -485,31 +485,24 @@ static int is_rfc2047_special(char ch) return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_')); } -static int add_rfc2047(char *buf, const char *line, int len, +static void add_rfc2047(struct strbuf *sb, const char *line, int len, const char *encoding) { - char *bp = buf; - int i, needquote; - char q_encoding[128]; - const char *q_encoding_fmt = "=?%s?q?"; + int i, last; - for (i = needquote = 0; !needquote && i < len; i++) { + for (i = 0; i < len; i++) { int ch = line[i]; if (non_ascii(ch)) - needquote++; - if ((i + 1 < len) && - (ch == '=' && line[i+1] == '?')) - needquote++; + goto needquote; + if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) + goto needquote; } - if (!needquote) - return sprintf(buf, "%.*s", len, line); - - i = snprintf(q_encoding, sizeof(q_encoding), q_encoding_fmt, encoding); - if (sizeof(q_encoding) < i) - die("Insanely long encoding name %s", encoding); - memcpy(bp, q_encoding, i); - bp += i; - for (i = 0; i < len; i++) { + strbuf_add(sb, line, len); + return; + +needquote: + strbuf_addf(sb, "=?%s?q?", encoding); + for (i = last = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; /* * We encode ' ' using '=20' even though rfc2047 @@ -518,15 +511,13 @@ static int add_rfc2047(char *buf, const char *line, int len, * leave the underscore in place. */ if (is_rfc2047_special(ch) || ch == ' ') { - sprintf(bp, "=%02X", ch); - bp += 3; + strbuf_add(sb, line + last, i - last); + strbuf_addf(sb, "=%02X", ch); + last = i + 1; } - else - *bp++ = ch; } - memcpy(bp, "?=", 2); - bp += 2; - return bp - buf; + strbuf_add(sb, line + last, len - last); + strbuf_addstr(sb, "?="); } static unsigned long bound_rfc2047(unsigned long len, const char *encoding) @@ -537,21 +528,21 @@ static unsigned long bound_rfc2047(unsigned long len, const char *encoding) return len * 3 + elen + 100; } -static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, +static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, const char *line, enum date_mode dmode, const char *encoding) { char *date; int namelen; unsigned long time; - int tz, ret; + int tz; const char *filler = " "; if (fmt == CMIT_FMT_ONELINE) - return 0; + return; date = strchr(line, '>'); if (!date) - return 0; + return; namelen = ++date - line; time = strtoul(date, &date, 10); tz = strtol(date, NULL, 10); @@ -560,42 +551,35 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, char *name_tail = strchr(line, '<'); int display_name_length; if (!name_tail) - return 0; + return; while (line < name_tail && isspace(name_tail[-1])) name_tail--; display_name_length = name_tail - line; filler = ""; - strcpy(buf, "From: "); - ret = strlen(buf); - ret += add_rfc2047(buf + ret, line, display_name_length, - encoding); - memcpy(buf + ret, name_tail, namelen - display_name_length); - ret += namelen - display_name_length; - buf[ret++] = '\n'; + strbuf_addstr(sb, "From: "); + add_rfc2047(sb, line, display_name_length, encoding); + strbuf_add(sb, name_tail, namelen - display_name_length); + strbuf_addch(sb, '\n'); } else { - ret = sprintf(buf, "%s: %.*s%.*s\n", what, + strbuf_addf(sb, "%s: %.*s%.*s\n", what, (fmt == CMIT_FMT_FULLER) ? 4 : 0, filler, namelen, line); } switch (fmt) { case CMIT_FMT_MEDIUM: - ret += sprintf(buf + ret, "Date: %s\n", - show_date(time, tz, dmode)); + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, dmode)); break; case CMIT_FMT_EMAIL: - ret += sprintf(buf + ret, "Date: %s\n", - show_date(time, tz, DATE_RFC2822)); + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822)); break; case CMIT_FMT_FULLER: - ret += sprintf(buf + ret, "%sDate: %s\n", what, - show_date(time, tz, dmode)); + strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, dmode)); break; default: /* notin' */ break; } - return ret; } static int is_empty_line(const char *line, int *len_p) @@ -607,16 +591,16 @@ static int is_empty_line(const char *line, int *len_p) return !len; } -static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev) +static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, + const struct commit *commit, int abbrev) { struct commit_list *parent = commit->parents; - int offset; if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) || !parent || !parent->next) - return 0; + return; - offset = sprintf(buf, "Merge:"); + strbuf_addstr(sb, "Merge:"); while (parent) { struct commit *p = parent->item; @@ -629,10 +613,9 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com dots = (abbrev && strlen(hex) != 40) ? "..." : ""; parent = parent->next; - offset += sprintf(buf + offset, " %s%s", hex, dots); + strbuf_addf(sb, " %s%s", hex, dots); } - buf[offset++] = '\n'; - return offset; + strbuf_addch(sb, '\n'); } static char *get_header(const struct commit *commit, const char *key) @@ -787,8 +770,8 @@ static void fill_person(struct interp *table, const char *msg, int len) interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601)); } -long format_commit_message(const struct commit *commit, const void *format, - char **buf_p, unsigned long *space_p) +void format_commit_message(const struct commit *commit, + const void *format, struct strbuf *sb) { struct interp table[] = { { "%H" }, /* commit hash */ @@ -841,6 +824,7 @@ long format_commit_message(const struct commit *commit, const void *format, }; struct commit_list *p; char parents[1024]; + unsigned long len; int i; enum { HEADER, SUBJECT, BODY } state; const char *msg = commit->buffer; @@ -921,20 +905,15 @@ long format_commit_message(const struct commit *commit, const void *format, if (!table[i].value) interp_set_entry(table, i, "<unknown>"); - do { - char *buf = *buf_p; - unsigned long len; - - len = interpolate(buf, *space_p, format, - table, ARRAY_SIZE(table)); - if (len < *space_p) - break; - ALLOC_GROW(buf, len + 1, *space_p); - *buf_p = buf; - } while (1); + len = interpolate(sb->buf + sb->len, strbuf_avail(sb), + format, table, ARRAY_SIZE(table)); + if (len > strbuf_avail(sb)) { + strbuf_grow(sb, len); + interpolate(sb->buf + sb->len, strbuf_avail(sb) + 1, + format, table, ARRAY_SIZE(table)); + } + strbuf_setlen(sb, sb->len + len); interp_clear_table(table, ARRAY_SIZE(table)); - - return strlen(*buf_p); } static void pp_header(enum cmit_fmt fmt, @@ -943,34 +922,24 @@ static void pp_header(enum cmit_fmt fmt, const char *encoding, const struct commit *commit, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p) + struct strbuf *sb) { int parents_shown = 0; for (;;) { const char *line = *msg_p; - char *dst; - int linelen = get_one_line(*msg_p, *len_p); - unsigned long len; + int linelen = get_one_line(*msg_p); if (!linelen) return; *msg_p += linelen; - *len_p -= linelen; if (linelen == 1) /* End of header */ return; - ALLOC_GROW(*buf_p, linelen + *ofs_p + 20, *space_p); - dst = *buf_p + *ofs_p; - if (fmt == CMIT_FMT_RAW) { - memcpy(dst, line, linelen); - *ofs_p += linelen; + strbuf_add(sb, line, linelen); continue; } @@ -988,10 +957,8 @@ static void pp_header(enum cmit_fmt fmt, parent = parent->next, num++) ; /* with enough slop */ - num = *ofs_p + num * 50 + 20; - ALLOC_GROW(*buf_p, num, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_merge_info(fmt, dst, commit, abbrev); + strbuf_grow(sb, num * 50 + 20); + add_merge_info(fmt, sb, commit, abbrev); parents_shown = 1; } @@ -1001,129 +968,99 @@ static void pp_header(enum cmit_fmt fmt, * FULLER shows both authors and dates. */ if (!memcmp(line, "author ", 7)) { - len = linelen; + unsigned long len = linelen; if (fmt == CMIT_FMT_EMAIL) len = bound_rfc2047(linelen, encoding); - ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_user_info("Author", fmt, dst, - line + 7, dmode, encoding); + strbuf_grow(sb, len + 80); + add_user_info("Author", fmt, sb, line + 7, dmode, encoding); } if (!memcmp(line, "committer ", 10) && (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) { - len = linelen; + unsigned long len = linelen; if (fmt == CMIT_FMT_EMAIL) len = bound_rfc2047(linelen, encoding); - ALLOC_GROW(*buf_p, *ofs_p + len + 80, *space_p); - dst = *buf_p + *ofs_p; - *ofs_p += add_user_info("Commit", fmt, dst, - line + 10, dmode, encoding); + strbuf_grow(sb, len + 80); + add_user_info("Commit", fmt, sb, line + 10, dmode, encoding); } } } static void pp_title_line(enum cmit_fmt fmt, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p, - int indent, + struct strbuf *sb, const char *subject, const char *after_subject, const char *encoding, int plain_non_ascii) { - char *title; - unsigned long title_alloc, title_len; + struct strbuf title; unsigned long len; - title_len = 0; - title_alloc = 80; - title = xmalloc(title_alloc); + strbuf_init(&title, 80); + for (;;) { const char *line = *msg_p; - int linelen = get_one_line(line, *len_p); - *msg_p += linelen; - *len_p -= linelen; + int linelen = get_one_line(line); + *msg_p += linelen; if (!linelen || is_empty_line(line, &linelen)) break; - if (title_alloc <= title_len + linelen + 2) { - title_alloc = title_len + linelen + 80; - title = xrealloc(title, title_alloc); - } - len = 0; - if (title_len) { + strbuf_grow(&title, linelen + 2); + if (title.len) { if (fmt == CMIT_FMT_EMAIL) { - len++; - title[title_len++] = '\n'; + strbuf_addch(&title, '\n'); } - len++; - title[title_len++] = ' '; + strbuf_addch(&title, ' '); } - memcpy(title + title_len, line, linelen); - title_len += linelen; + strbuf_add(&title, line, linelen); } /* Enough slop for the MIME header and rfc2047 */ - len = bound_rfc2047(title_len, encoding)+ 1000; + len = bound_rfc2047(title.len, encoding) + 1000; if (subject) len += strlen(subject); if (after_subject) len += strlen(after_subject); if (encoding) len += strlen(encoding); - ALLOC_GROW(*buf_p, title_len + *ofs_p + len, *space_p); + strbuf_grow(sb, title.len + len); if (subject) { - len = strlen(subject); - memcpy(*buf_p + *ofs_p, subject, len); - *ofs_p += len; - *ofs_p += add_rfc2047(*buf_p + *ofs_p, - title, title_len, encoding); + strbuf_addstr(sb, subject); + add_rfc2047(sb, title.buf, title.len, encoding); } else { - memcpy(*buf_p + *ofs_p, title, title_len); - *ofs_p += title_len; + strbuf_addbuf(sb, &title); } - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_addch(sb, '\n'); + if (plain_non_ascii) { const char *header_fmt = "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=%s\n" "Content-Transfer-Encoding: 8bit\n"; - *ofs_p += snprintf(*buf_p + *ofs_p, - *space_p - *ofs_p, - header_fmt, encoding); + strbuf_addf(sb, header_fmt, encoding); } if (after_subject) { - len = strlen(after_subject); - memcpy(*buf_p + *ofs_p, after_subject, len); - *ofs_p += len; + strbuf_addstr(sb, after_subject); } - free(title); if (fmt == CMIT_FMT_EMAIL) { - ALLOC_GROW(*buf_p, *ofs_p + 20, *space_p); - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_addch(sb, '\n'); } + strbuf_release(&title); } static void pp_remainder(enum cmit_fmt fmt, const char **msg_p, - unsigned long *len_p, - unsigned long *ofs_p, - char **buf_p, - unsigned long *space_p, + struct strbuf *sb, int indent) { int first = 1; for (;;) { const char *line = *msg_p; - int linelen = get_one_line(line, *len_p); + int linelen = get_one_line(line); *msg_p += linelen; - *len_p -= linelen; if (!linelen) break; @@ -1136,36 +1073,32 @@ static void pp_remainder(enum cmit_fmt fmt, } first = 0; - ALLOC_GROW(*buf_p, *ofs_p + linelen + indent + 20, *space_p); + strbuf_grow(sb, linelen + indent + 20); if (indent) { - memset(*buf_p + *ofs_p, ' ', indent); - *ofs_p += indent; + memset(sb->buf + sb->len, ' ', indent); + strbuf_setlen(sb, sb->len + indent); } - memcpy(*buf_p + *ofs_p, line, linelen); - *ofs_p += linelen; - (*buf_p)[(*ofs_p)++] = '\n'; + strbuf_add(sb, line, linelen); + strbuf_addch(sb, '\n'); } } -unsigned long pretty_print_commit(enum cmit_fmt fmt, - const struct commit *commit, - unsigned long len, - char **buf_p, unsigned long *space_p, - int abbrev, const char *subject, - const char *after_subject, +void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, + struct strbuf *sb, int abbrev, + const char *subject, const char *after_subject, enum date_mode dmode) { - unsigned long offset = 0; unsigned long beginning_of_body; int indent = 4; const char *msg = commit->buffer; int plain_non_ascii = 0; char *reencoded; const char *encoding; - char *buf; - if (fmt == CMIT_FMT_USERFORMAT) - return format_commit_message(commit, user_format, buf_p, space_p); + if (fmt == CMIT_FMT_USERFORMAT) { + format_commit_message(commit, user_format, sb); + return; + } encoding = (git_log_output_encoding ? git_log_output_encoding @@ -1175,7 +1108,6 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, reencoded = logmsg_reencode(commit, encoding); if (reencoded) { msg = reencoded; - len = strlen(reencoded); } if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) @@ -1190,14 +1122,13 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, if (fmt == CMIT_FMT_EMAIL && !after_subject) { int i, ch, in_body; - for (in_body = i = 0; (ch = msg[i]) && i < len; i++) { + for (in_body = i = 0; (ch = msg[i]); i++) { if (!in_body) { /* author could be non 7-bit ASCII but * the log may be so; skip over the * header part first. */ - if (ch == '\n' && - i + 1 < len && msg[i+1] == '\n') + if (ch == '\n' && msg[i+1] == '\n') in_body = 1; } else if (non_ascii(ch)) { @@ -1207,59 +1138,44 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, } } - pp_header(fmt, abbrev, dmode, encoding, - commit, &msg, &len, - &offset, buf_p, space_p); + pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb); if (fmt != CMIT_FMT_ONELINE && !subject) { - ALLOC_GROW(*buf_p, offset + 20, *space_p); - (*buf_p)[offset++] = '\n'; + strbuf_addch(sb, '\n'); } /* Skip excess blank lines at the beginning of body, if any... */ for (;;) { - int linelen = get_one_line(msg, len); + int linelen = get_one_line(msg); int ll = linelen; if (!linelen) break; if (!is_empty_line(msg, &ll)) break; msg += linelen; - len -= linelen; } /* These formats treat the title line specially. */ - if (fmt == CMIT_FMT_ONELINE - || fmt == CMIT_FMT_EMAIL) - pp_title_line(fmt, &msg, &len, &offset, - buf_p, space_p, indent, - subject, after_subject, encoding, - plain_non_ascii); - - beginning_of_body = offset; - if (fmt != CMIT_FMT_ONELINE) - pp_remainder(fmt, &msg, &len, &offset, - buf_p, space_p, indent); - - while (offset && isspace((*buf_p)[offset-1])) - offset--; + if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) + pp_title_line(fmt, &msg, sb, subject, + after_subject, encoding, plain_non_ascii); - ALLOC_GROW(*buf_p, offset + 20, *space_p); - buf = *buf_p; + beginning_of_body = sb->len; + if (fmt != CMIT_FMT_ONELINE) + pp_remainder(fmt, &msg, sb, indent); + strbuf_rtrim(sb); /* Make sure there is an EOLN for the non-oneline case */ if (fmt != CMIT_FMT_ONELINE) - buf[offset++] = '\n'; + strbuf_addch(sb, '\n'); /* * The caller may append additional body text in e-mail * format. Make sure we did not strip the blank line * between the header and the body. */ - if (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body) - buf[offset++] = '\n'; - buf[offset] = '\0'; + if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) + strbuf_addch(sb, '\n'); free(reencoded); - return offset; } struct commit *pop_commit(struct commit_list **stack) @@ -1338,12 +1254,12 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, next=next->next; } /* - * find the tips - * - * tips are nodes not reachable from any other node in the list - * - * the tips serve as a starting set for the work queue. - */ + * find the tips + * + * tips are nodes not reachable from any other node in the list + * + * the tips serve as a starting set for the work queue. + */ next=*list; insert = &work; while (next) { @@ -1370,9 +1286,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, if (pn) { /* * parents are only enqueued for emission - * when all their children have been emitted thereby - * guaranteeing topological order. - */ + * when all their children have been emitted thereby + * guaranteeing topological order. + */ pn->indegree--; if (!pn->indegree) { if (!lifo) @@ -1384,9 +1300,9 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, parents=parents->next; } /* - * work_item is a commit all of whose children - * have already been emitted. we can emit it now. - */ + * work_item is a commit all of whose children + * have already been emitted. we can emit it now. + */ *pptr = work_node->list_item; pptr = &(*pptr)->next; *pptr = NULL; @@ -1482,8 +1398,7 @@ static struct commit_list *merge_bases(struct commit *one, struct commit *two) } struct commit_list *get_merge_bases(struct commit *one, - struct commit *two, - int cleanup) + struct commit *two, int cleanup) { struct commit_list *list; struct commit **rslt; |