Skip to content

Commit 1ab03a5

Browse files
peffgitster
authored andcommitted
shortlog: skip format/parse roundtrip for internal traversal
The original git-shortlog command parsed the output of git-log, and the logic went something like this: 1. Read stdin looking for "author" lines. 2. Parse the identity into its name/email bits. 3. Apply mailmap to the name/email. 4. Reformat the identity into a single buffer that is our "key" for grouping entries (either a name by default, or "name <email>" if --email was given). The first part happens in read_from_stdin(), and the other three steps are part of insert_one_record(). When we do an internal traversal, we just swap out the stdin read in step 1 for reading the commit objects ourselves. Prior to 2db6b83 (shortlog: replace hand-parsing of author with pretty-printer, 2016-01-18), that made sense; we still had to parse the ident in the commit message. But after that commit, we use pretty.c's "%an <%ae>" to get the author ident (for simplicity). Which means that the pretty printer is doing a parse/format under the hood, and then we parse the result, apply the mailmap, and format the result again. Instead, we can just ask pretty.c to do all of those steps for us (including the mailmap via "%aN <%aE>", and not formatting the address when --email is missing). And then we can push steps 2-4 into read_from_stdin(). This speeds up "git shortlog -ns" on linux.git by about 3%, and eliminates a leak in insert_one_record() of the namemailbuf strbuf. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent edc74bc commit 1ab03a5

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed

builtin/shortlog.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,8 @@ static void insert_one_record(struct shortlog *log,
5252
const char *oneline)
5353
{
5454
struct string_list_item *item;
55-
const char *mailbuf, *namebuf;
56-
size_t namelen, maillen;
57-
struct strbuf namemailbuf = STRBUF_INIT;
58-
struct ident_split ident;
5955

60-
if (split_ident_line(&ident, author, strlen(author)))
61-
return;
62-
63-
namebuf = ident.name_begin;
64-
mailbuf = ident.mail_begin;
65-
namelen = ident.name_end - ident.name_begin;
66-
maillen = ident.mail_end - ident.mail_begin;
67-
68-
map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
69-
strbuf_add(&namemailbuf, namebuf, namelen);
70-
71-
if (log->email)
72-
strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
73-
74-
item = string_list_insert(&log->list, namemailbuf.buf);
56+
item = string_list_insert(&log->list, author);
7557

7658
if (log->summary)
7759
item->util = (void *)(UTIL_TO_INT(item) + 1);
@@ -114,9 +96,33 @@ static void insert_one_record(struct shortlog *log,
11496
}
11597
}
11698

99+
static int parse_stdin_author(struct shortlog *log,
100+
struct strbuf *out, const char *in)
101+
{
102+
const char *mailbuf, *namebuf;
103+
size_t namelen, maillen;
104+
struct ident_split ident;
105+
106+
if (split_ident_line(&ident, in, strlen(in)))
107+
return -1;
108+
109+
namebuf = ident.name_begin;
110+
mailbuf = ident.mail_begin;
111+
namelen = ident.name_end - ident.name_begin;
112+
maillen = ident.mail_end - ident.mail_begin;
113+
114+
map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
115+
strbuf_add(out, namebuf, namelen);
116+
if (log->email)
117+
strbuf_addf(out, " <%.*s>", (int)maillen, mailbuf);
118+
119+
return 0;
120+
}
121+
117122
static void read_from_stdin(struct shortlog *log)
118123
{
119124
struct strbuf author = STRBUF_INIT;
125+
struct strbuf mapped_author = STRBUF_INIT;
120126
struct strbuf oneline = STRBUF_INIT;
121127
static const char *author_match[2] = { "Author: ", "author " };
122128
static const char *committer_match[2] = { "Commit: ", "committer " };
@@ -134,9 +140,15 @@ static void read_from_stdin(struct shortlog *log)
134140
while (strbuf_getline_lf(&oneline, stdin) != EOF &&
135141
!oneline.len)
136142
; /* discard blanks */
137-
insert_one_record(log, v, oneline.buf);
143+
144+
strbuf_reset(&mapped_author);
145+
if (parse_stdin_author(log, &mapped_author, v) < 0)
146+
continue;
147+
148+
insert_one_record(log, mapped_author.buf, oneline.buf);
138149
}
139150
strbuf_release(&author);
151+
strbuf_release(&mapped_author);
140152
strbuf_release(&oneline);
141153
}
142154

@@ -153,7 +165,9 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
153165
ctx.date_mode.type = DATE_NORMAL;
154166
ctx.output_encoding = get_log_output_encoding();
155167

156-
fmt = log->committer ? "%cn <%ce>" : "%an <%ae>";
168+
fmt = log->committer ?
169+
(log->email ? "%cN <%cE>" : "%cN") :
170+
(log->email ? "%aN <%aE>" : "%aN");
157171

158172
format_commit_message(commit, fmt, &author, &ctx);
159173
if (!log->summary) {

0 commit comments

Comments
 (0)