mailmap.c::map_user() is simplified to take two strbuf parameters instead of statically allocated buffers. The buffers are still modified in-place, when mapping is required. It actually makes things easier for callers: - Caller must prepare the call by copying author name and email in strbuf (instead of copying in static buffer) - Caller can easily manipulate the buffer afterward. - Caller doesn't have to call strlen() to calculate the size of the new string. Signed-off-by: Antoine Pelisse <apelisse@xxxxxxxxx> --- builtin/blame.c | 164 +++++++++++++++++++++++++++------------------------- builtin/shortlog.c | 31 ++++------ mailmap.c | 51 ++++++++-------- mailmap.h | 4 +- pretty.c | 40 ++++++------- 5 files changed, 139 insertions(+), 151 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index dd4aff9..8586850 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1321,31 +1321,30 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt) * Information on commits, used for output. */ struct commit_info { - const char *author; - const char *author_mail; + struct strbuf author; + struct strbuf author_mail; unsigned long author_time; - const char *author_tz; + struct strbuf author_tz; /* filled only when asked for details */ - const char *committer; - const char *committer_mail; + struct strbuf committer; + struct strbuf committer_mail; unsigned long committer_time; - const char *committer_tz; + struct strbuf committer_tz; - const char *summary; + struct strbuf summary; }; /* * Parse author/committer line in the commit object buffer */ static void get_ac_line(const char *inbuf, const char *what, - int person_len, char *person, - int mail_len, char *mail, - unsigned long *time, const char **tz) + struct strbuf *name, struct strbuf *mail, + unsigned long *time, struct strbuf *tz) { struct ident_split ident; - int len, tzlen, maillen, namelen; - char *tmp, *endp, *mailpos; + int len; + char *tmp, *endp; tmp = strstr(inbuf, what); if (!tmp) @@ -1356,51 +1355,61 @@ static void get_ac_line(const char *inbuf, const char *what, len = strlen(tmp); else len = endp - tmp; - if (person_len <= len) - goto error_out; if (split_ident_line(&ident, tmp, len)) { error_out: /* Ugh */ - *tz = "(unknown)"; - strcpy(person, *tz); - strcpy(mail, *tz); + tmp = "(unknown)"; + strbuf_addstr(name, tmp); + strbuf_addstr(mail, tmp); + strbuf_addstr(tz, tmp); *time = 0; return; } - namelen = ident.name_end - ident.name_begin; - memcpy(person, ident.name_begin, namelen); - person[namelen] = 0; + len = ident.name_end - ident.name_begin; + strbuf_add(name, ident.name_begin, len); - maillen = ident.mail_end - ident.mail_begin + 2; - memcpy(mail, ident.mail_begin - 1, maillen); - mail[maillen] = 0; + len = ident.mail_end - ident.mail_begin; + strbuf_add(mail, ident.mail_begin, len); *time = strtoul(ident.date_begin, NULL, 10); - tzlen = ident.tz_end - ident.tz_begin; + len = ident.tz_end - ident.tz_begin; + strbuf_add(tz, ident.tz_begin, len); - /* Place tz at the end of person */ - *tz = tmp = person + person_len - (tzlen + 1); - memcpy(tmp, ident.tz_begin, tzlen); - tmp[tzlen] = 0; - - if (!mailmap.nr) - return; - - /* + /* * Now, convert both name and e-mail using mailmap */ - if (map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) { - /* Add a trailing '>' to email, since map_user returns plain emails - Note: It already has '<', since we replace from mail+1 */ - mailpos = memchr(mail, '\0', mail_len); - if (mailpos && mailpos-mail < mail_len - 1) { - *mailpos = '>'; - *(mailpos+1) = '\0'; - } - } + if (mailmap.nr) + map_user(&mailmap, mail, name); + + strbuf_insert(mail, 0, "<", 1); + strbuf_addch(mail, '>'); +} + +static void commit_info_init(struct commit_info *ci) +{ + + strbuf_init(&ci->author, 0); + strbuf_init(&ci->author_mail, 0); + strbuf_init(&ci->author_tz, 0); + strbuf_init(&ci->committer, 0); + strbuf_init(&ci->committer_mail, 0); + strbuf_init(&ci->committer_tz, 0); + strbuf_init(&ci->summary, 0); +} + +static void commit_info_destroy(struct commit_info *ci) +{ + + strbuf_release(&ci->author); + strbuf_release(&ci->author_mail); + strbuf_release(&ci->author_tz); + strbuf_release(&ci->committer); + strbuf_release(&ci->committer_mail); + strbuf_release(&ci->committer_tz); + strbuf_release(&ci->summary); } static void get_commit_info(struct commit *commit, @@ -1410,11 +1419,8 @@ static void get_commit_info(struct commit *commit, int len; const char *subject, *encoding; char *reencoded, *message; - static char author_name[1024]; - static char author_mail[1024]; - static char committer_name[1024]; - static char committer_mail[1024]; - static char summary_buf[1024]; + + commit_info_init(ret); /* * We've operated without save_commit_buffer, so @@ -1432,11 +1438,7 @@ static void get_commit_info(struct commit *commit, encoding = get_log_output_encoding(); reencoded = logmsg_reencode(commit, encoding); message = reencoded ? reencoded : commit->buffer; - ret->author = author_name; - ret->author_mail = author_mail; - get_ac_line(message, "\nauthor ", - sizeof(author_name), author_name, - sizeof(author_mail), author_mail, + get_ac_line(message, "\nauthor ", &ret->author, &ret->author_mail, &ret->author_time, &ret->author_tz); if (!detailed) { @@ -1444,21 +1446,16 @@ static void get_commit_info(struct commit *commit, return; } - ret->committer = committer_name; - ret->committer_mail = committer_mail; - get_ac_line(message, "\ncommitter ", - sizeof(committer_name), committer_name, - sizeof(committer_mail), committer_mail, - &ret->committer_time, &ret->committer_tz); + get_ac_line(message, "\ncommitter ", &ret->committer, + &ret->committer_mail, &ret->committer_time, + &ret->committer_tz); - ret->summary = summary_buf; len = find_commit_subject(message, &subject); - if (len && len < sizeof(summary_buf)) { - memcpy(summary_buf, subject, len); - summary_buf[len] = 0; - } else { - sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1)); - } + if (len) + strbuf_add(&ret->summary, subject, len); + else + strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1)); + free(reencoded); } @@ -1487,15 +1484,15 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) suspect->commit->object.flags |= METAINFO_SHOWN; get_commit_info(suspect->commit, &ci, 1); - printf("author %s\n", ci.author); - printf("author-mail %s\n", ci.author_mail); + printf("author %s\n", ci.author.buf); + printf("author-mail %s\n", ci.author_mail.buf); printf("author-time %lu\n", ci.author_time); - printf("author-tz %s\n", ci.author_tz); - printf("committer %s\n", ci.committer); - printf("committer-mail %s\n", ci.committer_mail); + printf("author-tz %s\n", ci.author_tz.buf); + printf("committer %s\n", ci.committer.buf); + printf("committer-mail %s\n", ci.committer_mail.buf); printf("committer-time %lu\n", ci.committer_time); - printf("committer-tz %s\n", ci.committer_tz); - printf("summary %s\n", ci.summary); + printf("committer-tz %s\n", ci.committer_tz.buf); + printf("summary %s\n", ci.summary.buf); if (suspect->commit->object.flags & UNINTERESTING) printf("boundary\n"); if (suspect->previous) { @@ -1503,6 +1500,9 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) printf("previous %s ", sha1_to_hex(prev->commit->object.sha1)); write_name_quoted(prev->path, stdout, '\n'); } + + commit_info_destroy(&ci); + return 1; } @@ -1689,11 +1689,11 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) if (opt & OUTPUT_ANNOTATE_COMPAT) { const char *name; if (opt & OUTPUT_SHOW_EMAIL) - name = ci.author_mail; + name = ci.author_mail.buf; else - name = ci.author; + name = ci.author.buf; printf("\t(%10s\t%10s\t%d)", name, - format_time(ci.author_time, ci.author_tz, + format_time(ci.author_time, ci.author_tz.buf, show_raw_time), ent->lno + 1 + cnt); } else { @@ -1712,14 +1712,14 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) const char *name; int pad; if (opt & OUTPUT_SHOW_EMAIL) - name = ci.author_mail; + name = ci.author_mail.buf; else - name = ci.author; + name = ci.author.buf; pad = longest_author - utf8_strwidth(name); printf(" (%s%*s %10s", name, pad, "", format_time(ci.author_time, - ci.author_tz, + ci.author_tz.buf, show_raw_time)); } printf(" %*d) ", @@ -1734,6 +1734,8 @@ static void emit_other(struct scoreboard *sb, struct blame_entry *ent, int opt) if (sb->final_buf_size && cp[-1] != '\n') putchar('\n'); + + commit_info_destroy(&ci); } static void output(struct scoreboard *sb, int option) @@ -1858,9 +1860,9 @@ static void find_alignment(struct scoreboard *sb, int *option) suspect->commit->object.flags |= METAINFO_SHOWN; get_commit_info(suspect->commit, &ci, 1); if (*option & OUTPUT_SHOW_EMAIL) - num = utf8_strwidth(ci.author_mail); + num = utf8_strwidth(ci.author_mail.buf); else - num = utf8_strwidth(ci.author); + num = utf8_strwidth(ci.author.buf); if (longest_author < num) longest_author = num; } @@ -1872,6 +1874,8 @@ static void find_alignment(struct scoreboard *sb, int *option) longest_dst_lines = num; if (largest_score < ent_score(sb, e)) largest_score = ent_score(sb, e); + + commit_info_destroy(&ci); } max_orig_digits = decimal_width(longest_src_lines); max_digits = decimal_width(longest_dst_lines); diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 03c6cd7..20e8599 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -36,39 +36,30 @@ static void insert_one_record(struct shortlog *log, const char *dot3 = log->common_repo_prefix; char *buffer, *p; struct string_list_item *item; - char namebuf[1024]; - char emailbuf[1024]; - size_t len; const char *eol; struct strbuf subject = STRBUF_INIT; + struct strbuf name = STRBUF_INIT; + struct strbuf mail = STRBUF_INIT; struct ident_split ident; if (split_ident_line(&ident, author, strlen(author))) return; - /* copy author name to namebuf, to support matching on both name and email */ - len = ident.name_end - ident.name_begin; - memcpy(namebuf, ident.name_begin, len); - namebuf[len] = 0; + strbuf_add(&mail, ident.mail_begin, ident.mail_end - ident.mail_begin); + strbuf_add(&name, ident.name_begin, ident.name_end - ident.name_begin); - /* copy email name to emailbuf, to allow email replacement as well */ - len = ident.mail_end - ident.mail_begin; - memcpy(emailbuf, ident.mail_begin, len); - emailbuf[len] = 0; + map_user(&log->mailmap, &mail, &name); - map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf)); - len = strlen(namebuf); + if (log->email) + strbuf_addf(&name, " <%s>", mail.buf); - if (log->email) { - size_t room = sizeof(namebuf) - len - 1; - int maillen = strlen(emailbuf); - snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf); - } - - item = string_list_insert(&log->list, namebuf); + item = string_list_insert(&log->list, name.buf); if (item->util == NULL) item->util = xcalloc(1, sizeof(struct string_list)); + strbuf_release(&name); + strbuf_release(&mail); + /* Skip any leading whitespace, including any blank lines. */ while (*oneline && isspace(*oneline)) oneline++; diff --git a/mailmap.c b/mailmap.c index 3bc6491..d5bffc6 100644 --- a/mailmap.c +++ b/mailmap.c @@ -187,57 +187,52 @@ void clear_mailmap(struct string_list *map) debug_mm("mailmap: cleared\n"); } -int map_user(struct string_list *map, - char *email, int maxlen_email, char *name, int maxlen_name) +int map_user(struct string_list *map, struct strbuf *mail, struct strbuf *name) { - char *end_of_email; + struct string_list_item *item; struct mailmap_entry *me; - struct strbuf mailbuf = STRBUF_INIT; + struct strbuf lowermail = STRBUF_INIT; int i; - /* figure out space requirement for email */ - end_of_email = strchr(email, '>'); - if (!end_of_email) { - /* email passed in might not be wrapped in <>, but end with a \0 */ - end_of_email = memchr(email, '\0', maxlen_email); - if (!end_of_email) - return 0; - } - /* downcase the email address */ - strbuf_grow(&mailbuf, end_of_email - email); - for (i = 0; i < end_of_email - email; i++) - strbuf_addch(&mailbuf, tolower(email[i])); + strbuf_grow(&lowermail, mail->len); + for (i = 0; i < mail->len; i++) + strbuf_addch(&lowermail, tolower(mail->buf[i])); - debug_mm("map_user: map '%s' <%s>\n", name, mailbuf.buf); - item = string_list_lookup(map, mailbuf.buf); + debug_mm("map_user: map '%s' <%s>\n", name->buf, lowermail.buf); + item = string_list_lookup(map, lowermail.buf); if (item != NULL) { me = (struct mailmap_entry *)item->util; if (me->namemap.nr) { /* The item has multiple items, so we'll look up on name too */ /* If the name is not found, we choose the simple entry */ - struct string_list_item *subitem = string_list_lookup(&me->namemap, name); + struct string_list_item *subitem = string_list_lookup(&me->namemap, name->buf); if (subitem) item = subitem; } } - strbuf_release(&mailbuf); + strbuf_release(&lowermail); if (item != NULL) { struct mailmap_info *mi = (struct mailmap_info *)item->util; - if (mi->name == NULL && (mi->email == NULL || maxlen_email == 0)) { + if (mi->name == NULL && mi->email == NULL) { debug_mm("map_user: -- (no simple mapping)\n"); return 0; } - if (maxlen_email && mi->email) - strlcpy(email, mi->email, maxlen_email); - else - *end_of_email = '\0'; - if (maxlen_name && mi->name) - strlcpy(name, mi->name, maxlen_name); - debug_mm("map_user: to '%s' <%s>\n", name, mi->email ? mi->email : ""); + if (mi->email) { + strbuf_reset(mail); + strbuf_addstr(mail, mi->email); + } + + if (mi->name) { + strbuf_reset(name); + strbuf_addstr(name, mi->name); + } + + debug_mm("map_user: to '%s' <%s>\n", name->buf, mi->email ? mi->email : ""); return 1; } + debug_mm("map_user: --\n"); return 0; } diff --git a/mailmap.h b/mailmap.h index d5c3664..88dca51 100644 --- a/mailmap.h +++ b/mailmap.h @@ -4,7 +4,5 @@ int read_mailmap(struct string_list *map, char **repo_abbrev); void clear_mailmap(struct string_list *map); -int map_user(struct string_list *mailmap, - char *email, int maxlen_email, char *name, int maxlen_name); - +int map_user(struct string_list *map, struct strbuf *name, struct strbuf *mail); #endif diff --git a/pretty.c b/pretty.c index 350d1df..d05c675 100644 --- a/pretty.c +++ b/pretty.c @@ -593,14 +593,14 @@ char *logmsg_reencode(const struct commit *commit, return out; } -static int mailmap_name(char *email, int email_len, char *name, int name_len) +static int mailmap_name(struct strbuf *mail, struct strbuf *name) { static struct string_list *mail_map; if (!mail_map) { mail_map = xcalloc(1, sizeof(*mail_map)); read_mailmap(mail_map, NULL); } - return mail_map->nr && map_user(mail_map, email, email_len, name, name_len); + return mail_map->nr && map_user(mail_map, mail, name); } static size_t format_person_part(struct strbuf *sb, char part, @@ -610,39 +610,39 @@ static size_t format_person_part(struct strbuf *sb, char part, const int placeholder_len = 2; int tz; unsigned long date = 0; - char person_name[1024]; - char person_mail[1024]; + struct strbuf person_name = STRBUF_INIT; + struct strbuf person_mail = STRBUF_INIT; struct ident_split s; - const char *name_start, *name_end, *mail_start, *mail_end; if (split_ident_line(&s, msg, len) < 0) goto skip; - name_start = s.name_begin; - name_end = s.name_end; - mail_start = s.mail_begin; - mail_end = s.mail_end; + strbuf_add(&person_name, s.name_begin, (int)(s.name_end - s.name_begin)); + strbuf_add(&person_mail, s.mail_begin, (int)(s.mail_end - s.mail_begin)); if (part == 'N' || part == 'E') { /* mailmap lookup */ - snprintf(person_name, sizeof(person_name), "%.*s", - (int)(name_end - name_start), name_start); - snprintf(person_mail, sizeof(person_mail), "%.*s", - (int)(mail_end - mail_start), mail_start); - mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name)); - name_start = person_name; - name_end = name_start + strlen(person_name); - mail_start = person_mail; - mail_end = mail_start + strlen(person_mail); + mailmap_name(&person_mail, &person_name); } if (part == 'n' || part == 'N') { /* name */ - strbuf_add(sb, name_start, name_end-name_start); + strbuf_addbuf(sb, &person_name); + + strbuf_release(&person_name); + strbuf_release(&person_mail); + return placeholder_len; } if (part == 'e' || part == 'E') { /* email */ - strbuf_add(sb, mail_start, mail_end-mail_start); + strbuf_addbuf(sb, &person_mail); + + strbuf_release(&person_name); + strbuf_release(&person_mail); + return placeholder_len; } + strbuf_release(&person_name); + strbuf_release(&person_mail); + if (!s.date_begin) goto skip; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html