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

[PATCH 12/34] diff: release strbuf after use in show_stats()

From
Rene Scharfe <l.s.r@web.de>
Date
Aug 30, 2017, 17:49 UTC
Message-ID
<20170830175005.20756-13-l.s.r@web.de>
In-Reply-To
<20170830175005.20756-1-l.s.r@web.de>
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 diff.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/diff.c b/diff.c
index 33c65f492d..64cdcf2331 100644
--- a/diff.c
+++ b/diff.c
@@ -2334,255 +2334,256 @@ void print_stat_summary(FILE *fp, int files,
 static void show_stats(struct diffstat_t *data, struct diff_options *options)
 {
 	int i, len, add, del, adds = 0, dels = 0;
 	uintmax_t max_change = 0, max_len = 0;
 	int total_files = data->nr, count;
 	int width, name_width, graph_width, number_width = 0, bin_width = 0;
 	const char *reset, *add_c, *del_c;
 	int extra_shown = 0;
 	const char *line_prefix = diff_line_prefix(options);
 	struct strbuf out = STRBUF_INIT;
 
 	if (data->nr == 0)
 		return;
 
 	count = options->stat_count ? options->stat_count : data->nr;
 
 	reset = diff_get_color_opt(options, DIFF_RESET);
 	add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
 	del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
 	/*
 	 * Find the longest filename and max number of changes
 	 */
 	for (i = 0; (i < count) && (i < data->nr); i++) {
 		struct diffstat_file *file = data->files[i];
 		uintmax_t change = file->added + file->deleted;
 
 		if (!file->is_interesting && (change == 0)) {
 			count++; /* not shown == room for one more */
 			continue;
 		}
 		fill_print_name(file);
 		len = strlen(file->print_name);
 		if (max_len < len)
 			max_len = len;
 
 		if (file->is_unmerged) {
 			/* "Unmerged" is 8 characters */
 			bin_width = bin_width < 8 ? 8 : bin_width;
 			continue;
 		}
 		if (file->is_binary) {
 			/* "Bin XXX -> YYY bytes" */
 			int w = 14 + decimal_width(file->added)
 				+ decimal_width(file->deleted);
 			bin_width = bin_width < w ? w : bin_width;
 			/* Display change counts aligned with "Bin" */
 			number_width = 3;
 			continue;
 		}
 
 		if (max_change < change)
 			max_change = change;
 	}
 	count = i; /* where we can stop scanning in data->files[] */
 
 	/*
 	 * We have width = stat_width or term_columns() columns total.
 	 * We want a maximum of min(max_len, stat_name_width) for the name part.
 	 * We want a maximum of min(max_change, stat_graph_width) for the +- part.
 	 * We also need 1 for " " and 4 + decimal_width(max_change)
 	 * for " | NNNN " and one the empty column at the end, altogether
 	 * 6 + decimal_width(max_change).
 	 *
 	 * If there's not enough space, we will use the smaller of
 	 * stat_name_width (if set) and 5/8*width for the filename,
 	 * and the rest for constant elements + graph part, but no more
 	 * than stat_graph_width for the graph part.
 	 * (5/8 gives 50 for filename and 30 for the constant parts + graph
 	 * for the standard terminal size).
 	 *
 	 * In other words: stat_width limits the maximum width, and
 	 * stat_name_width fixes the maximum width of the filename,
 	 * and is also used to divide available columns if there
 	 * aren't enough.
 	 *
 	 * Binary files are displayed with "Bin XXX -> YYY bytes"
 	 * instead of the change count and graph. This part is treated
 	 * similarly to the graph part, except that it is not
 	 * "scaled". If total width is too small to accommodate the
 	 * guaranteed minimum width of the filename part and the
 	 * separators and this message, this message will "overflow"
 	 * making the line longer than the maximum width.
 	 */
 
 	if (options->stat_width == -1)
 		width = term_columns() - strlen(line_prefix);
 	else
 		width = options->stat_width ? options->stat_width : 80;
 	number_width = decimal_width(max_change) > number_width ?
 		decimal_width(max_change) : number_width;
 
 	if (options->stat_graph_width == -1)
 		options->stat_graph_width = diff_stat_graph_width;
 
 	/*
 	 * Guarantee 3/8*16==6 for the graph part
 	 * and 5/8*16==10 for the filename part
 	 */
 	if (width < 16 + 6 + number_width)
 		width = 16 + 6 + number_width;
 
 	/*
 	 * First assign sizes that are wanted, ignoring available width.
 	 * strlen("Bin XXX -> YYY bytes") == bin_width, and the part
 	 * starting from "XXX" should fit in graph_width.
 	 */
 	graph_width = max_change + 4 > bin_width ? max_change : bin_width - 4;
 	if (options->stat_graph_width &&
 	    options->stat_graph_width < graph_width)
 		graph_width = options->stat_graph_width;
 
 	name_width = (options->stat_name_width > 0 &&
 		      options->stat_name_width < max_len) ?
 		options->stat_name_width : max_len;
 
 	/*
 	 * Adjust adjustable widths not to exceed maximum width
 	 */
 	if (name_width + number_width + 6 + graph_width > width) {
 		if (graph_width > width * 3/8 - number_width - 6) {
 			graph_width = width * 3/8 - number_width - 6;
 			if (graph_width < 6)
 				graph_width = 6;
 		}
 
 		if (options->stat_graph_width &&
 		    graph_width > options->stat_graph_width)
 			graph_width = options->stat_graph_width;
 		if (name_width > width - number_width - 6 - graph_width)
 			name_width = width - number_width - 6 - graph_width;
 		else
 			graph_width = width - number_width - 6 - name_width;
 	}
 
 	/*
 	 * From here name_width is the width of the name area,
 	 * and graph_width is the width of the graph area.
 	 * max_change is used to scale graph properly.
 	 */
 	for (i = 0; i < count; i++) {
 		const char *prefix = "";
 		struct diffstat_file *file = data->files[i];
 		char *name = file->print_name;
 		uintmax_t added = file->added;
 		uintmax_t deleted = file->deleted;
 		int name_len;
 
 		if (!file->is_interesting && (added + deleted == 0))
 			continue;
 
 		/*
 		 * "scale" the filename
 		 */
 		len = name_width;
 		name_len = strlen(name);
 		if (name_width < name_len) {
 			char *slash;
 			prefix = "...";
 			len -= 3;
 			name += name_len - len;
 			slash = strchr(name, '/');
 			if (slash)
 				name = slash;
 		}
 
 		if (file->is_binary) {
 			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
 			strbuf_addf(&out, " %*s", number_width, "Bin");
 			if (!added && !deleted) {
 				strbuf_addch(&out, '\n');
 				emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 						 out.buf, out.len, 0);
 				strbuf_reset(&out);
 				continue;
 			}
 			strbuf_addf(&out, " %s%"PRIuMAX"%s",
 				del_c, deleted, reset);
 			strbuf_addstr(&out, " -> ");
 			strbuf_addf(&out, "%s%"PRIuMAX"%s",
 				add_c, added, reset);
 			strbuf_addstr(&out, " bytes\n");
 			emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 					 out.buf, out.len, 0);
 			strbuf_reset(&out);
 			continue;
 		}
 		else if (file->is_unmerged) {
 			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
 			strbuf_addstr(&out, " Unmerged\n");
 			emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 					 out.buf, out.len, 0);
 			strbuf_reset(&out);
 			continue;
 		}
 
 		/*
 		 * scale the add/delete
 		 */
 		add = added;
 		del = deleted;
 
 		if (graph_width <= max_change) {
 			int total = scale_linear(add + del, graph_width, max_change);
 			if (total < 2 && add && del)
 				/* width >= 2 due to the sanity check */
 				total = 2;
 			if (add < del) {
 				add = scale_linear(add, graph_width, max_change);
 				del = total - add;
 			} else {
 				del = scale_linear(del, graph_width, max_change);
 				add = total - del;
 			}
 		}
 		strbuf_addf(&out, " %s%-*s |", prefix, len, name);
 		strbuf_addf(&out, " %*"PRIuMAX"%s",
 			number_width, added + deleted,
 			added + deleted ? " " : "");
 		show_graph(&out, '+', add, add_c, reset);
 		show_graph(&out, '-', del, del_c, reset);
 		strbuf_addch(&out, '\n');
 		emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
 				 out.buf, out.len, 0);
 		strbuf_reset(&out);
 	}
 
 	for (i = 0; i < data->nr; i++) {
 		struct diffstat_file *file = data->files[i];
 		uintmax_t added = file->added;
 		uintmax_t deleted = file->deleted;
 
 		if (file->is_unmerged ||
 		    (!file->is_interesting && (added + deleted == 0))) {
 			total_files--;
 			continue;
 		}
 
 		if (!file->is_binary) {
 			adds += added;
 			dels += deleted;
 		}
 		if (i < count)
 			continue;
 		if (!extra_shown)
 			emit_diff_symbol(options,
 					 DIFF_SYMBOL_STATS_SUMMARY_ABBREV,
 					 NULL, 0, 0);
 		extra_shown = 1;
 	}
 
 	print_stat_summary_inserts_deletes(options, total_files, adds, dels);
+	strbuf_release(&out);
 }
 
 static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
-- 
2.14.1
Previous: Rene ScharfeNext: Rene Scharfe
Message 34 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.