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

[PATCH 2/3 v4] diff --stat: better alignment for binary files

From
Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Date
Feb 14, 2012, 23:45 UTC
Message-ID
<1329263146-19215-2-git-send-email-zbyszek@in.waw.pl>
In-Reply-To
<1329263146-19215-1-git-send-email-zbyszek@in.waw.pl>

The output for binary and unmerged files was not updated in 'diff --stat': use the full terminal width'. This fixes this omission and modifies the graph width logic to include enough space for "Bin XXX -> YYY bytes".

If changes to binary files are mixed with changes to text files, change counts are padded to take at least three columns. And the other way around, if change counts require more than three columns, then "Bin"s is padded to align with the change count. This way, the +- part starts in the same column as "XXX -> YYY" part for binary files. This makes the graph easier to parse visually thanks to the empty column. This mimics the old layout of diff --stat.

Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
---
 diff.c                 | 39 ++++++++++++++++++++++++++++++++-------
 t/t4012-diff-binary.sh | 17 +++++++++++++++++
 2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/diff.c b/diff.c
index 4dc2b5c..0732623 100644
--- a/diff.c
+++ b/diff.c
@@ -1326,8 +1326,8 @@ 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;
-	int width, name_width, graph_width, number_width, count;
+	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;
 	const char *line_prefix = "";
 	int extra_shown = 0;
@@ -1363,8 +1363,21 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		if (max_len < len)
 			max_len = len;
 
-		if (file->is_binary || file->is_unmerged)
+		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;
 	}
@@ -1389,10 +1402,19 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 	 * 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 accomodate 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.
 	 */
 
 	width = options->stat_width ? options->stat_width : term_columns();
-	number_width = decimal_width(max_change);
+	number_width = decimal_width(max_change) > number_width ?
+		decimal_width(max_change) : number_width;
 
 	/*
 	 * Guarantee 3/8*16==6 for the graph part
@@ -1403,8 +1425,11 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 
 	/*
 	 * First assign sizes that are wanted, ignoring available width.
+	 * (strlen("Bin XXX -> YYY bytes") is bin_width + 4)
 	 */
-	graph_width = max_change < 40 ? max_change : 40;
+	graph_width = max_change + 4 > bin_width ? max_change : bin_width - 4;
+	if (graph_width > 40)
+		graph_width = 40;
 	name_width = (options->stat_name_width > 0 &&
 		      options->stat_name_width < max_len) ?
 		options->stat_name_width : max_len;
@@ -1458,7 +1483,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		if (data->files[i]->is_binary) {
 			fprintf(options->file, "%s", line_prefix);
 			show_name(options->file, prefix, name, len);
-			fprintf(options->file, "  Bin ");
+			fprintf(options->file, " %*s ", number_width, "Bin");
 			fprintf(options->file, "%s%"PRIuMAX"%s",
 				del_c, deleted, reset);
 			fprintf(options->file, " -> ");
@@ -1471,7 +1496,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
 		else if (data->files[i]->is_unmerged) {
 			fprintf(options->file, "%s", line_prefix);
 			show_name(options->file, prefix, name, len);
-			fprintf(options->file, "  Unmerged\n");
+			fprintf(options->file, " Unmerged\n");
 			continue;
 		}
 
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 2d9f9a0..ea0b376 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -90,4 +90,21 @@ test_expect_success 'diff --no-index with binary creation' '
 	test_cmp expected actual
 '
 
+cat >expect <<EOF
+ binfile  |   Bin 0 -> 1026 bytes
+ textfile | 10000 ++++++++++++++++++++++++++++++++++++++++
+EOF
+
+test_expect_success 'diff with binary files and big change count
+
+	Verify that "Bin" and the change count are properly aligned when
+	change count is big' '
+	echo X | dd of=binfile bs=1k seek=1 &&
+	git add binfile &&
+	seq 10000 > textfile &&
+	git add textfile &&
+	git diff --cached --stat binfile textfile | grep " | " > actual
+	test_cmp expect actual
+'
+
 test_done
-- 
1.7.9.6.ga1838.dirty
Previous: Zbigniew Jędrzejewski-SzmekNext: Zbigniew Jędrzejewski-Szmek
Message 30 of 46 in “(unknown)”
  1. Zbigniew Jędrzejewski-SzmekFeb 9, 2012
  2. 1/4 Move git_version_string to help.c in preparation for diff changesZbigniew Jędrzejewski-Szmek, Feb 9, 2012
  3. Junio C HamanoFeb 10, 2012
  4. 2/4 help.c: make term_columns() cached and export itZbigniew Jędrzejewski-Szmek, Feb 9, 2012
  5. Junio C HamanoFeb 10, 2012
  6. 3/4 diff --stat: use the real terminal widthZbigniew Jędrzejewski-Szmek, Feb 9, 2012
  7. Junio C HamanoFeb 10, 2012
  8. Nguyen Thai Ngoc DuyFeb 10, 2012
  9. Zbigniew Jędrzejewski-SzmekFeb 10, 2012
  10. Nguyen Thai Ngoc DuyFeb 10, 2012
  11. 0/3 diff --stat: use the real terminal widthZbigniew Jędrzejewski-Szmek, Feb 10, 2012
  12. 1/3 Move git_version_string to help.c before diff changesZbigniew Jędrzejewski-Szmek, Feb 10, 2012
  13. Junio C HamanoFeb 10, 2012
  14. 2/3 help.c: make term_columns() cached and export itZbigniew Jędrzejewski-Szmek, Feb 10, 2012
  15. Nguyen Thai Ngoc DuyFeb 11, 2012
  16. Zbigniew Jędrzejewski-SzmekFeb 11, 2012
  17. Junio C HamanoFeb 12, 2012
  18. 1/2 Save terminal width before setting up pager and export term_columns()Zbigniew Jędrzejewski-Szmek, Feb 12, 2012
  19. Junio C HamanoFeb 13, 2012
  20. Nguyen Thai Ngoc DuyFeb 14, 2012
  21. Zbigniew Jędrzejewski-SzmekFeb 14, 2012
  22. 2/2 Rename lineno_width to decimal_width and export itZbigniew Jędrzejewski-Szmek, Feb 12, 2012
  23. Junio C HamanoFeb 13, 2012
  24. make lineno_width() from blame reusable for othersZbigniew Jędrzejewski-Szmek, Feb 14, 2012
  25. 3/3 diff --stat: use the real terminal widthZbigniew Jędrzejewski-Szmek, Feb 10, 2012
  26. Junio C HamanoFeb 10, 2012
  27. diff --stat: use the full terminal widthZbigniew Jędrzejewski-Szmek, Feb 12, 2012
  28. Junio C HamanoFeb 14, 2012
  29. 1/3 diff --stat: use the full terminal widthZbigniew Jędrzejewski-Szmek, Feb 14, 2012
  30. 2/3 diff --stat: better alignment for binary filesZbigniew Jędrzejewski-Szmek, Feb 14, 2012
  31. 3/3 Update diff --stat output in tests and tutorialZbigniew Jędrzejewski-Szmek, Feb 14, 2012
  32. Junio C HamanoFeb 15, 2012
  33. 1/3 diff --stat: tests for long filenames and big change countsZbigniew Jędrzejewski-Szmek, Feb 15, 2012
  34. 2/3 diff --stat: use the full terminal widthZbigniew Jędrzejewski-Szmek, Feb 15, 2012
  35. Junio C HamanoFeb 15, 2012
  36. 3/3 diff --stat: use less columns for change countsZbigniew Jędrzejewski-Szmek, Feb 15, 2012
  37. Nguyen Thai Ngoc DuyFeb 15, 2012
  38. Junio C HamanoFeb 15, 2012
  39. Junio C HamanoFeb 15, 2012
  40. Zbigniew Jędrzejewski-SzmekFeb 16, 2012
  41. Junio C HamanoFeb 16, 2012
  42. Junio C HamanoFeb 15, 2012
  43. Junio C HamanoFeb 15, 2012
  44. Johannes SixtFeb 15, 2012
  45. 4/4 diff --stat: use most of the space for file namesZbigniew Jędrzejewski-Szmek, Feb 9, 2012
  46. Junio C HamanoFeb 10, 2012

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.