git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 27/34] shortlog: release strbuf after use in insert_one_record()

From
Jeff King <peff@peff.net>
Date
Sep 8, 2017, 04:36 UTC
Message-ID
<20170908043633.smytugbn7ge4twlm@sigill.intra.peff.net>
In-Reply-To
<20170908035648.jhm6ypxkwwms4bqu@sigill.intra.peff.net>
On Thu, Sep 07, 2017 at 11:56:48PM -0400, Jeff King wrote:
Show 15 quoted lines
> > True; I do not think string_list API does.  But for this particular
> > application, I suspect that we can by looking at the util field of
> > the item returned.  A newly created one has NULL, but we always make
> > it non-NULL before leaving this function.
> 
> Yeah, I agree that would work here.
> 
> I also wondered if we could get away with avoiding the malloc entirely
> here. Especially in the "shortlog -n" case, it is identical to the name
> field we already have in ident.name. So ideally we'd do a lookup to see
> if we have the entry before allocating anything (since we do one lookup
> per commit, but only insert once per unique author).
> 
> But that doesn't quite work, because ident.name doesn't put to a
> NUL-terminated string, and string_list only handles strings.

I happened to look at this more while digging on an unrelated shortlog bug. I think the whole thing could actually be reorganized a bit.

We call insert_one_record() from shortlog_add_commit(). The latter formats "%an <%ae>", only to have the former parse it back to its constituent parts. That seems rather silly.

This is an artifact of shortlog's original mode, which was to parse "git log" output. But for an internal traversal, we can just format the correct item right off the bat. That part of insert_one_record() is also where we handle the mailmap mapping. But again, the internal traversal can just "%aE" to format that correctly in the first place.

IOW, something like the patch below, which pushes the re-parsing out to the stdin code-path, and lets the internal traversal format directly into the final buffer. It seems to be about 3% faster than the existing code, and fixes the leak (by dropping that variable entirely).

-Peff
---
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 43c4799ea9..e29875b843 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -52,26 +52,8 @@ static void insert_one_record(struct shortlog *log,
 			      const char *oneline)
 {
 	struct string_list_item *item;
-	const char *mailbuf, *namebuf;
-	size_t namelen, maillen;
-	struct strbuf namemailbuf = STRBUF_INIT;
-	struct ident_split ident;
 
-	if (split_ident_line(&ident, author, strlen(author)))
-		return;
-
-	namebuf = ident.name_begin;
-	mailbuf = ident.mail_begin;
-	namelen = ident.name_end - ident.name_begin;
-	maillen = ident.mail_end - ident.mail_begin;
-
-	map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
-	strbuf_add(&namemailbuf, namebuf, namelen);
-
-	if (log->email)
-		strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
-
-	item = string_list_insert(&log->list, namemailbuf.buf);
+	item = string_list_insert(&log->list, author);
 
 	if (log->summary)
 		item->util = (void *)(UTIL_TO_INT(item) + 1);
@@ -114,9 +96,33 @@ static void insert_one_record(struct shortlog *log,
 	}
 }
 
+static int parse_stdin_author(struct shortlog *log,
+			       struct strbuf *out, const char *in)
+{
+	const char *mailbuf, *namebuf;
+	size_t namelen, maillen;
+	struct ident_split ident;
+
+	if (split_ident_line(&ident, in, strlen(in)))
+		return -1;
+
+	namebuf = ident.name_begin;
+	mailbuf = ident.mail_begin;
+	namelen = ident.name_end - ident.name_begin;
+	maillen = ident.mail_end - ident.mail_begin;
+
+	map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
+	strbuf_add(out, namebuf, namelen);
+	if (log->email)
+		strbuf_addf(out, " <%.*s>", (int)maillen, mailbuf);
+
+	return 0;
+}
+
 static void read_from_stdin(struct shortlog *log)
 {
 	struct strbuf author = STRBUF_INIT;
+	struct strbuf mapped_author = STRBUF_INIT;
 	struct strbuf oneline = STRBUF_INIT;
 	static const char *author_match[2] = { "Author: ", "author " };
 	static const char *committer_match[2] = { "Commit: ", "committer " };
@@ -134,9 +140,15 @@ static void read_from_stdin(struct shortlog *log)
 		while (strbuf_getline_lf(&oneline, stdin) != EOF &&
 		       !oneline.len)
 			; /* discard blanks */
-		insert_one_record(log, v, oneline.buf);
+
+		strbuf_reset(&mapped_author);
+		if (parse_stdin_author(log, &mapped_author, v) < 0)
+			continue;
+
+		insert_one_record(log, mapped_author.buf, oneline.buf);
 	}
 	strbuf_release(&author);
+	strbuf_release(&mapped_author);
 	strbuf_release(&oneline);
 }
 
@@ -153,7 +165,9 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
 	ctx.date_mode.type = DATE_NORMAL;
 	ctx.output_encoding = get_log_output_encoding();
 
-	fmt = log->committer ? "%cn <%ce>" : "%an <%ae>";
+	fmt = log->committer ?
+		(log->email ? "%cN <%cE>" : "%cN") :
+		(log->email ? "%aN <%aE>" : "%aN");
 
 	format_commit_message(commit, fmt, &author, &ctx);
 	if (!log->summary) {
Previous: Jeff KingNext: Junio C Hamano
Message 55 of 75 in “plug strbuf memory leaks”
  1. 00/34 plug strbuf memory leaksRene Scharfe, Aug 30, 2017
  2. 01/34 am: release strbufs after use in detect_patch_format()Rene Scharfe, Aug 30, 2017
  3. Stefan BellerAug 31, 2017
  4. 02/34 am: release strbuf on error return in hg_patch_to_mail()Rene Scharfe, Aug 30, 2017
  5. 05/34 clean: release strbuf after use in remove_dirs()Rene Scharfe, Aug 30, 2017
  6. 06/34 clone: release strbuf after use in remove_junk()Rene Scharfe, Aug 30, 2017
  7. Junio C HamanoSep 6, 2017
  8. René ScharfeSep 10, 2017
  9. Jeff KingSep 10, 2017
  10. René ScharfeSep 10, 2017
  11. Jeff KingSep 10, 2017
  12. René ScharfeSep 11, 2017
  13. Jeff KingSep 13, 2017
  14. 07/34 commit: release strbuf on error return in commit_tree_extended()Rene Scharfe, Aug 30, 2017
  15. Stefan BellerAug 31, 2017
  16. 19/34 merge: release strbuf after use in write_merge_heads()Rene Scharfe, Aug 30, 2017
  17. 10/34 diff: release strbuf after use in diff_summary()Rene Scharfe, Aug 30, 2017
  18. Stefan BellerAug 31, 2017
  19. 14/34 help: release strbuf on error return in exec_man_man()Rene Scharfe, Aug 30, 2017
  20. 15/34 help: release strbuf on error return in exec_woman_emacs()Rene Scharfe, Aug 30, 2017
  21. 18/34 merge: release strbuf after use in save_state()Rene Scharfe, Aug 30, 2017
  22. 16/34 mailinfo: release strbuf after use in handle_from()Rene Scharfe, Aug 30, 2017
  23. 17/34 mailinfo: release strbuf on error return in handle_boundary()Rene Scharfe, Aug 30, 2017
  24. Martin ÅgrenAug 30, 2017
  25. René ScharfeAug 31, 2017
  26. Martin ÅgrenSep 5, 2017
  27. 13/34 help: release strbuf on error return in exec_man_konqueror()Rene Scharfe, Aug 30, 2017
  28. 09/34 convert: release strbuf on error return in filter_buffer_or_fd()Rene Scharfe, Aug 30, 2017
  29. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  30. Stefan BellerAug 31, 2017
  31. 03/34 am: release strbuf after use in safe_to_abort()Rene Scharfe, Aug 30, 2017
  32. 04/34 check-ref-format: release strbuf after use in check_ref_format_branch()Rene Scharfe, Aug 30, 2017
  33. 11/34 diff: release strbuf after use in show_rename_copy()Rene Scharfe, Aug 30, 2017
  34. 12/34 diff: release strbuf after use in show_stats()Rene Scharfe, Aug 30, 2017
  35. 20/34 notes: release strbuf after use in notes_copy_from_stdin()Rene Scharfe, Aug 30, 2017
  36. 02/34 am: release strbuf on error return in hg_patch_to_mail()Rene Scharfe, Aug 30, 2017
  37. 03/34 am: release strbuf after use in safe_to_abort()Rene Scharfe, Aug 30, 2017
  38. 09/34 convert: release strbuf on error return in filter_buffer_or_fd()Rene Scharfe, Aug 30, 2017
  39. 04/34 check-ref-format: release strbuf after use in check_ref_format_branch()Rene Scharfe, Aug 30, 2017
  40. 12/34 diff: release strbuf after use in show_stats()Rene Scharfe, Aug 30, 2017
  41. 11/34 diff: release strbuf after use in show_rename_copy()Rene Scharfe, Aug 30, 2017
  42. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  43. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  44. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  45. 22/34 remote: release strbuf after use in read_remote_branches()Rene Scharfe, Aug 30, 2017
  46. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  47. 25/34 send-pack: release strbuf on error return in send_pack()Rene Scharfe, Aug 30, 2017
  48. 23/34 remote: release strbuf after use in migrate_file()Rene Scharfe, Aug 30, 2017
  49. 24/34 remote: release strbuf after use in set_url()Rene Scharfe, Aug 30, 2017
  50. 27/34 shortlog: release strbuf after use in insert_one_record()Rene Scharfe, Aug 30, 2017
  51. Junio C HamanoSep 6, 2017
  52. Jeff KingSep 7, 2017
  53. Junio C HamanoSep 8, 2017
  54. Jeff KingSep 8, 2017
  55. Jeff KingSep 8, 2017
  56. Junio C HamanoSep 8, 2017
  57. shortlog: skip format/parse roundtrip for internal traversalJeff King, Sep 8, 2017
  58. René ScharfeSep 10, 2017
  59. Jeff KingSep 10, 2017
  60. 26/34 sha1_file: release strbuf on error return in index_path()Rene Scharfe, Aug 30, 2017
  61. 08/34 connect: release strbuf on error return in git_connect()Rene Scharfe, Aug 30, 2017
  62. 28/34 sequencer: release strbuf after use in save_head()Rene Scharfe, Aug 30, 2017
  63. 32/34 vcs-svn: release strbuf after use in end_revision()Rene Scharfe, Aug 30, 2017
  64. 34/34 wt-status: release strbuf after use in wt_longstatus_print_tracking()Rene Scharfe, Aug 30, 2017
  65. Junio C HamanoSep 6, 2017
  66. René ScharfeSep 10, 2017
  67. Junio C HamanoSep 10, 2017
  68. 31/34 utf8: release strbuf on error return in strbuf_utf8_replace()Rene Scharfe, Aug 30, 2017
  69. 33/34 wt-status: release strbuf after use in read_rebase_todolist()Rene Scharfe, Aug 30, 2017
  70. 21/34 refs: release strbuf on error return in write_pseudoref()Rene Scharfe, Aug 30, 2017
  71. 25/34 send-pack: release strbuf on error return in send_pack()Rene Scharfe, Aug 30, 2017
  72. 29/34 transport-helper: release strbuf after use in process_connect_service()Rene Scharfe, Aug 30, 2017
  73. 30/34 userdiff: release strbuf after use in userdiff_get_textconv()Rene Scharfe, Aug 30, 2017
  74. Stefan BellerAug 31, 2017
  75. Junio C HamanoSep 6, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.