shortlog: replace hand-parsing of author with pretty-printer
When gathering the author and oneline subject for each commit, we hand-parse the commit headers to find the "author" line, and then continue past to the blank line at the end of the header. We can replace this tricky hand-parsing by simply asking the pretty-printer for the relevant items. This also decouples the author and oneline parsing, opening up some new optimizations in further commits. One reason to avoid the pretty-printer is that it might be less efficient than hand-parsing. However, I measured no slowdown at all running "git shortlog -ns HEAD" on linux.git. As a bonus, we also fix a memory leak in the (uncommon) case that the author field is blank. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
50250491bd
commit
2db6b83d18
|
@ -113,45 +113,35 @@ static void read_from_stdin(struct shortlog *log)
|
||||||
|
|
||||||
void shortlog_add_commit(struct shortlog *log, struct commit *commit)
|
void shortlog_add_commit(struct shortlog *log, struct commit *commit)
|
||||||
{
|
{
|
||||||
const char *author = NULL, *buffer;
|
struct strbuf author = STRBUF_INIT;
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf oneline = STRBUF_INIT;
|
||||||
struct strbuf ufbuf = STRBUF_INIT;
|
struct pretty_print_context ctx = {0};
|
||||||
|
|
||||||
pp_commit_easy(CMIT_FMT_RAW, commit, &buf);
|
ctx.fmt = CMIT_FMT_USERFORMAT;
|
||||||
buffer = buf.buf;
|
ctx.abbrev = log->abbrev;
|
||||||
while (*buffer && *buffer != '\n') {
|
ctx.subject = "";
|
||||||
const char *eol = strchr(buffer, '\n');
|
ctx.after_subject = "";
|
||||||
|
ctx.date_mode.type = DATE_NORMAL;
|
||||||
|
ctx.output_encoding = get_log_output_encoding();
|
||||||
|
|
||||||
if (eol == NULL)
|
format_commit_message(commit, "%an <%ae>", &author, &ctx);
|
||||||
eol = buffer + strlen(buffer);
|
/* we can detect a total failure only by seeing " <>" in the output */
|
||||||
else
|
if (author.len <= 3) {
|
||||||
eol++;
|
|
||||||
|
|
||||||
if (starts_with(buffer, "author "))
|
|
||||||
author = buffer + 7;
|
|
||||||
buffer = eol;
|
|
||||||
}
|
|
||||||
if (!author) {
|
|
||||||
warning(_("Missing author: %s"),
|
warning(_("Missing author: %s"),
|
||||||
oid_to_hex(&commit->object.oid));
|
oid_to_hex(&commit->object.oid));
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
if (log->user_format) {
|
|
||||||
struct pretty_print_context ctx = {0};
|
if (log->user_format)
|
||||||
ctx.fmt = CMIT_FMT_USERFORMAT;
|
pretty_print_commit(&ctx, commit, &oneline);
|
||||||
ctx.abbrev = log->abbrev;
|
else
|
||||||
ctx.subject = "";
|
format_commit_message(commit, "%s", &oneline, &ctx);
|
||||||
ctx.after_subject = "";
|
|
||||||
ctx.date_mode.type = DATE_NORMAL;
|
insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>");
|
||||||
ctx.output_encoding = get_log_output_encoding();
|
|
||||||
pretty_print_commit(&ctx, commit, &ufbuf);
|
out:
|
||||||
buffer = ufbuf.buf;
|
strbuf_release(&author);
|
||||||
} else if (*buffer) {
|
strbuf_release(&oneline);
|
||||||
buffer++;
|
|
||||||
}
|
|
||||||
insert_one_record(log, author, !*buffer ? "<none>" : buffer);
|
|
||||||
strbuf_release(&ufbuf);
|
|
||||||
strbuf_release(&buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_from_rev(struct rev_info *rev, struct shortlog *log)
|
static void get_from_rev(struct rev_info *rev, struct shortlog *log)
|
||||||
|
|
Loading…
Reference in New Issue