summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
authorLibravatar Jeff King <peff@peff.net>2016-01-18 15:02:48 -0500
committerLibravatar Junio C Hamano <gitster@pobox.com>2016-01-19 09:54:14 -0800
commit2db6b83d189bb82d1d45805fa6c85a9c8b507920 (patch)
tree52a4a02c06f5b3ad67d60ed1310be2bd827e94b1 /builtin
parentshortlog: use strbufs to read from stdin (diff)
downloadtgif-2db6b83d189bb82d1d45805fa6c85a9c8b507920.tar.xz
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>
Diffstat (limited to 'builtin')
-rw-r--r--builtin/shortlog.c62
1 files changed, 26 insertions, 36 deletions
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 6c0a72edef..1261ec4dd0 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -113,45 +113,35 @@ static void read_from_stdin(struct shortlog *log)
void shortlog_add_commit(struct shortlog *log, struct commit *commit)
{
- const char *author = NULL, *buffer;
- struct strbuf buf = STRBUF_INIT;
- struct strbuf ufbuf = STRBUF_INIT;
-
- pp_commit_easy(CMIT_FMT_RAW, commit, &buf);
- buffer = buf.buf;
- while (*buffer && *buffer != '\n') {
- const char *eol = strchr(buffer, '\n');
-
- if (eol == NULL)
- eol = buffer + strlen(buffer);
- else
- eol++;
-
- if (starts_with(buffer, "author "))
- author = buffer + 7;
- buffer = eol;
- }
- if (!author) {
+ struct strbuf author = STRBUF_INIT;
+ struct strbuf oneline = STRBUF_INIT;
+ struct pretty_print_context ctx = {0};
+
+ ctx.fmt = CMIT_FMT_USERFORMAT;
+ ctx.abbrev = log->abbrev;
+ ctx.subject = "";
+ ctx.after_subject = "";
+ ctx.date_mode.type = DATE_NORMAL;
+ ctx.output_encoding = get_log_output_encoding();
+
+ format_commit_message(commit, "%an <%ae>", &author, &ctx);
+ /* we can detect a total failure only by seeing " <>" in the output */
+ if (author.len <= 3) {
warning(_("Missing author: %s"),
oid_to_hex(&commit->object.oid));
- return;
- }
- if (log->user_format) {
- struct pretty_print_context ctx = {0};
- ctx.fmt = CMIT_FMT_USERFORMAT;
- ctx.abbrev = log->abbrev;
- ctx.subject = "";
- ctx.after_subject = "";
- ctx.date_mode.type = DATE_NORMAL;
- ctx.output_encoding = get_log_output_encoding();
- pretty_print_commit(&ctx, commit, &ufbuf);
- buffer = ufbuf.buf;
- } else if (*buffer) {
- buffer++;
+ goto out;
}
- insert_one_record(log, author, !*buffer ? "<none>" : buffer);
- strbuf_release(&ufbuf);
- strbuf_release(&buf);
+
+ if (log->user_format)
+ pretty_print_commit(&ctx, commit, &oneline);
+ else
+ format_commit_message(commit, "%s", &oneline, &ctx);
+
+ insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>");
+
+out:
+ strbuf_release(&author);
+ strbuf_release(&oneline);
}
static void get_from_rev(struct rev_info *rev, struct shortlog *log)