From 3c020bd528d5dc320b82bd787670edfe6695f097 Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Sat, 5 Jan 2013 22:26:38 +0100 Subject: Use split_ident_line to parse author and committer Currently blame.c::get_acline(), pretty.c::pp_user_info() and shortlog.c::insert_one_record() are parsing author name, email, time and tz themselves. Use ident.c::split_ident_line() for better code reuse. Signed-off-by: Antoine Pelisse Signed-off-by: Junio C Hamano --- builtin/blame.c | 59 +++++++++++++++++++----------------------------------- builtin/shortlog.c | 36 +++++++++------------------------ 2 files changed, 31 insertions(+), 64 deletions(-) (limited to 'builtin') diff --git a/builtin/blame.c b/builtin/blame.c index cfae569905..dd4aff91e0 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1343,8 +1343,9 @@ static void get_ac_line(const char *inbuf, const char *what, int mail_len, char *mail, unsigned long *time, const char **tz) { - int len, tzlen, maillen; - char *tmp, *endp, *timepos, *mailpos; + struct ident_split ident; + int len, tzlen, maillen, namelen; + char *tmp, *endp, *mailpos; tmp = strstr(inbuf, what); if (!tmp) @@ -1355,7 +1356,10 @@ static void get_ac_line(const char *inbuf, const char *what, len = strlen(tmp); else len = endp - tmp; - if (person_len <= len) { + if (person_len <= len) + goto error_out; + + if (split_ident_line(&ident, tmp, len)) { error_out: /* Ugh */ *tz = "(unknown)"; @@ -1364,47 +1368,26 @@ static void get_ac_line(const char *inbuf, const char *what, *time = 0; return; } - memcpy(person, tmp, len); - tmp = person; - tmp += len; - *tmp = 0; - while (person < tmp && *tmp != ' ') - tmp--; - if (tmp <= person) - goto error_out; - *tz = tmp+1; - tzlen = (person+len)-(tmp+1); + namelen = ident.name_end - ident.name_begin; + memcpy(person, ident.name_begin, namelen); + person[namelen] = 0; - *tmp = 0; - while (person < tmp && *tmp != ' ') - tmp--; - if (tmp <= person) - goto error_out; - *time = strtoul(tmp, NULL, 10); - timepos = tmp; + maillen = ident.mail_end - ident.mail_begin + 2; + memcpy(mail, ident.mail_begin - 1, maillen); + mail[maillen] = 0; - *tmp = 0; - while (person < tmp && !(*tmp == ' ' && tmp[1] == '<')) - tmp--; - if (tmp <= person) - return; - mailpos = tmp + 1; - *tmp = 0; - maillen = timepos - tmp; - memcpy(mail, mailpos, maillen); + *time = strtoul(ident.date_begin, NULL, 10); - if (!mailmap.nr) - return; + tzlen = ident.tz_end - ident.tz_begin; - /* - * mailmap expansion may make the name longer. - * make room by pushing stuff down. - */ - tmp = person + person_len - (tzlen + 1); - memmove(tmp, *tz, tzlen); + /* Place tz at the end of person */ + *tz = tmp = person + person_len - (tzlen + 1); + memcpy(tmp, ident.tz_begin, tzlen); tmp[tzlen] = 0; - *tz = tmp; + + if (!mailmap.nr) + return; /* * Now, convert both name and e-mail using mailmap diff --git a/builtin/shortlog.c b/builtin/shortlog.c index b316cf37ca..03c6cd7e86 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -40,40 +40,24 @@ static void insert_one_record(struct shortlog *log, char emailbuf[1024]; size_t len; const char *eol; - const char *boemail, *eoemail; struct strbuf subject = STRBUF_INIT; + struct ident_split ident; - boemail = strchr(author, '<'); - if (!boemail) - return; - eoemail = strchr(boemail, '>'); - if (!eoemail) + if (split_ident_line(&ident, author, strlen(author))) return; /* copy author name to namebuf, to support matching on both name and email */ - memcpy(namebuf, author, boemail - author); - len = boemail - author; - while (len > 0 && isspace(namebuf[len-1])) - len--; + len = ident.name_end - ident.name_begin; + memcpy(namebuf, ident.name_begin, len); namebuf[len] = 0; /* copy email name to emailbuf, to allow email replacement as well */ - memcpy(emailbuf, boemail+1, eoemail - boemail); - emailbuf[eoemail - boemail - 1] = 0; - - if (!map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf))) { - while (author < boemail && isspace(*author)) - author++; - for (len = 0; - len < sizeof(namebuf) - 1 && author + len < boemail; - len++) - namebuf[len] = author[len]; - while (0 < len && isspace(namebuf[len-1])) - len--; - namebuf[len] = '\0'; - } - else - len = strlen(namebuf); + len = ident.mail_end - ident.mail_begin; + memcpy(emailbuf, ident.mail_begin, len); + emailbuf[len] = 0; + + map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf)); + len = strlen(namebuf); if (log->email) { size_t room = sizeof(namebuf) - len - 1; -- cgit v1.2.3 From ea02ffa38571084007eb7c63f650d0011e44a3dd Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Sat, 5 Jan 2013 22:26:40 +0100 Subject: mailmap: simplify map_user() interface Simplify map_user(), mostly to avoid copies of string buffers. It also simplifies caller functions. map_user() directly receive pointers and length from the commit buffer as mail and name. If mapping of the user and mail can be done, the pointer is updated to a new location. Lengths are also updated if necessary. The caller of map_user() can then copy the new email and name if necessary. Signed-off-by: Antoine Pelisse Signed-off-by: Junio C Hamano --- builtin/blame.c | 156 +++++++++++++++++++++++++++-------------------------- builtin/shortlog.c | 32 +++++------ 2 files changed, 93 insertions(+), 95 deletions(-) (limited to 'builtin') diff --git a/builtin/blame.c b/builtin/blame.c index dd4aff91e0..9d20e25552 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1321,31 +1321,31 @@ 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; + size_t len, maillen, namelen; + char *tmp, *endp; + const char *namebuf, *mailbuf; tmp = strstr(inbuf, what); if (!tmp) @@ -1356,51 +1356,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; + namebuf = ident.name_begin; - maillen = ident.mail_end - ident.mail_begin + 2; - memcpy(mail, ident.mail_begin - 1, maillen); - mail[maillen] = 0; + maillen = ident.mail_end - ident.mail_begin; + mailbuf = ident.mail_begin; *time = strtoul(ident.date_begin, NULL, 10); - tzlen = ident.tz_end - ident.tz_begin; - - /* 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; + len = ident.tz_end - ident.tz_begin; + strbuf_add(tz, ident.tz_begin, len); /* * 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'; - } - } + map_user(&mailmap, &mailbuf, &maillen, + &namebuf, &namelen); + + strbuf_addf(mail, "<%.*s>", (int)maillen, mailbuf); + strbuf_add(name, namebuf, namelen); +} + +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 +1420,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 +1439,8 @@ 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, + &ret->author, &ret->author_mail, &ret->author_time, &ret->author_tz); if (!detailed) { @@ -1444,21 +1448,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, &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 +1486,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 +1502,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 +1691,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 +1714,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 +1736,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 +1862,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 +1876,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 03c6cd7e86..1eeed0ffd8 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -36,36 +36,28 @@ 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 *mailbuf, *namebuf; + size_t namelen, maillen; const char *eol; struct strbuf subject = STRBUF_INIT; + struct strbuf namemailbuf = 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; + namebuf = ident.name_begin; + mailbuf = ident.mail_begin; + namelen = ident.name_end - ident.name_begin; + maillen = ident.mail_end - ident.mail_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, &mailbuf, &maillen, &namebuf, &namelen); + strbuf_add(&namemailbuf, namebuf, namelen); - map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf)); - len = strlen(namebuf); + if (log->email) + strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf); - 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, namemailbuf.buf); if (item->util == NULL) item->util = xcalloc(1, sizeof(struct string_list)); -- cgit v1.2.3 From ea57bc0d41b03cc1528be5fafa5eb8bfd4f773cb Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Sat, 5 Jan 2013 22:26:43 +0100 Subject: log: add --use-mailmap option Add the --use-mailmap option to log commands. It allows to display names from mailmap file when displaying logs, whatever the format used. Signed-off-by: Antoine Pelisse Signed-off-by: Junio C Hamano --- builtin/log.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/log.c b/builtin/log.c index e7b7db1cac..d2bd8cea78 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -22,6 +22,7 @@ #include "branch.h" #include "streaming.h" #include "version.h" +#include "mailmap.h" /* Set a default date-time format for git log ("log.date" config variable) */ static const char *default_date_mode = NULL; @@ -94,11 +95,12 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, struct rev_info *rev, struct setup_revision_opt *opt) { struct userformat_want w; - int quiet = 0, source = 0; + int quiet = 0, source = 0, mailmap = 0; const struct option builtin_log_options[] = { OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")), OPT_BOOLEAN(0, "source", &source, N_("show source")), + OPT_BOOLEAN(0, "use-mailmap", &mailmap, N_("Use mail map file")), { OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"), PARSE_OPT_OPTARG, decorate_callback}, OPT_END() @@ -136,6 +138,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, if (source) rev->show_source = 1; + if (mailmap) { + rev->mailmap = xcalloc(1, sizeof(struct string_list)); + read_mailmap(rev->mailmap, NULL); + } + if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) { /* * "log --pretty=raw" is special; ignore UI oriented -- cgit v1.2.3 From e6bb5f78fb351c89a80826befda3c8f06f91f249 Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Sat, 5 Jan 2013 22:26:46 +0100 Subject: log: add log.mailmap configuration option Teach "log.mailmap" configuration variable to turn "--use-mailmap" option on to "git log", "git show" and "git whatchanged". The "--no-use-mailmap" option from the command line can countermand the setting. Signed-off-by: Antoine Pelisse Signed-off-by: Junio C Hamano --- builtin/log.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'builtin') diff --git a/builtin/log.c b/builtin/log.c index d2bd8cea78..16e6520a5d 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -31,6 +31,7 @@ static int default_abbrev_commit; static int default_show_root = 1; static int decoration_style; static int decoration_given; +static int use_mailmap_config; static const char *fmt_patch_subject_prefix = "PATCH"; static const char *fmt_pretty; @@ -106,6 +107,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, OPT_END() }; + mailmap = use_mailmap_config; argc = parse_options(argc, argv, prefix, builtin_log_options, builtin_log_usage, PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN | @@ -358,6 +360,11 @@ static int git_log_config(const char *var, const char *value, void *cb) } if (!prefixcmp(var, "color.decorate.")) return parse_decorate_color_config(var, 15, value); + if (!strcmp(var, "log.mailmap")) { + use_mailmap_config = git_config_bool(var, value); + return 0; + } + if (grep_config(var, value, cb) < 0) return -1; return git_diff_ui_config(var, value, cb); -- cgit v1.2.3