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

[PATCH 3/3] diff --stat: sometimes use non-linear scaling.

From
Junio C Hamano <junkio@cox.net>
Date
Sep 27, 2006, 02:40 UTC
Message-ID
<7vfyeejakq.fsf@assigned-by-dhcp.cox.net>

When some files have big changes and others are touched only slightly, diffstat graph did not show differences among smaller changes that well. This changes the graph scaling to non-linear algorithm in such a case.

Without this, "git show --stat fd88d9c" gives:
 .gitignore                       |    1
 Documentation/git-tar-tree.txt   |    3 +
 Documentation/git-upload-tar.txt |   39 -----------
 Documentation/git.txt            |    4 -
 Makefile                         |    1
 builtin-tar-tree.c               |  130 +++++++++++++++-----------------------
 builtin-upload-tar.c             |   74 ----------------------
 git.c                            |    1
 8 files changed, 53 insertions(+), 200 deletions(-)
while with this, it shows:
 .gitignore                       |    1
 Documentation/git-tar-tree.txt   |    3 +++++++++
 Documentation/git-upload-tar.txt |   39 -----------------------------
 Documentation/git.txt            |    4 -----------
 Makefile                         |    1
 builtin-tar-tree.c               |  130 +++++++++++++++-----------------------
 builtin-upload-tar.c             |   74 ----------------------------------
 git.c                            |    1
 8 files changed, 53 insertions(+), 200 deletions(-)
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * Jan Engelhardt wondered about doing non-linear scaling on the
   kernel list and this is an experimental patch to do so.  I do
   not seriously consider this for inclusion but it is more of a
   "see if people like it" patch.
 Makefile |    2 +-
 diff.c   |   29 +++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index 28091d6..0fc59c4 100644
--- a/Makefile
+++ b/Makefile
@@ -304,7 +304,7 @@ BUILTIN_OBJS = \
 	builtin-write-tree.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
-LIBS = $(GITLIBS) -lz
+LIBS = $(GITLIBS) -lz -lm
 
 #
 # Platform specific tweaks
diff --git a/diff.c b/diff.c
index 13aac2d..163ef48 100644
--- a/diff.c
+++ b/diff.c
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>
+#include <math.h>
 #include "cache.h"
 #include "quote.h"
 #include "diff.h"
@@ -555,6 +556,16 @@ static int scale_linear(int it, int widt
 	return (it * width * 2 + max_change) / (max_change * 2);
 }
 
+static int scale_non_linear(int it, int width, int max_change)
+{
+	/*
+	 * round(width * log(it)/log(max_change))
+	 */
+	if (!it || !max_change)
+		return 0;
+	return (int)(0.5 + width * log(it) / log(max_change));
+}
+
 static void show_name(const char *prefix, const char *name, int len,
 		      const char *reset, const char *set)
 {
@@ -574,10 +585,11 @@ static void show_graph(char ch, int cnt,
 static void show_stats(struct diffstat_t* data, struct diff_options *options)
 {
 	int i, len, add, del, total, adds = 0, dels = 0;
-	int max_change = 0, max_len = 0;
+	int max_change = 0, max_len = 0, min_change = 0;
 	int total_files = data->nr;
 	int width, name_width;
 	const char *reset, *set, *add_c, *del_c;
+	int non_linear_scale = 0;
 
 	if (data->nr == 0)
 		return;
@@ -595,12 +607,12 @@ static void show_stats(struct diffstat_t
 			width = name_width + 15;
 	}
 
-	/* Find the longest filename and max number of changes */
 	reset = diff_get_color(options->color_diff, DIFF_RESET);
 	set = diff_get_color(options->color_diff, DIFF_PLAIN);
 	add_c = diff_get_color(options->color_diff, DIFF_FILE_NEW);
 	del_c = diff_get_color(options->color_diff, DIFF_FILE_OLD);
 
+	/* Find the longest filename and max/min number of changes */
 	for (i = 0; i < data->nr; i++) {
 		struct diffstat_file *file = data->files[i];
 		int change = file->added + file->deleted;
@@ -620,6 +632,8 @@ static void show_stats(struct diffstat_t
 			continue;
 		if (max_change < change)
 			max_change = change;
+		if (0 < change && (!min_change || change < min_change))
+			min_change = change;
 	}
 
 	/* Compute the width of the graph part;
@@ -635,6 +649,12 @@ static void show_stats(struct diffstat_t
 	else
 		width = max_change;
 
+	/* See if the minimum change is shown with the normal scale
+	 * and if not switch to non-linear scale
+	 */
+	if (min_change && !scale_linear(min_change, width, max_change))
+		non_linear_scale = 1;
+
 	for (i = 0; i < data->nr; i++) {
 		const char *prefix = "";
 		char *name = data->files[i]->name;
@@ -684,6 +704,11 @@ static void show_stats(struct diffstat_t
 
 		if (max_change < width)
 			;
+		else if (non_linear_scale) {
+			total = scale_non_linear(total, width, max_change);
+			add = scale_linear(add, total, add + del);
+			del = total - add;
+		}
 		else {
 			total = scale_linear(total, width, max_change);
 			add = scale_linear(add, width, max_change);
-- 
1.4.2.1.gf80a
Next: David Rientjes
Message 1 of 18 in “diff --stat: sometimes use non-linear scaling.”
  1. 3/3 diff --stat: sometimes use non-linear scaling.Junio C Hamano, Sep 27, 2006
  2. David RientjesSep 27, 2006
  3. Junio C HamanoSep 27, 2006
  4. David RientjesSep 27, 2006
  5. Junio C HamanoSep 27, 2006
  6. David RientjesSep 27, 2006
  7. Junio C HamanoSep 27, 2006
  8. David RientjesSep 27, 2006
  9. Johannes SchindelinSep 27, 2006
  10. Petr BaudisOct 6, 2006
  11. Johannes SchindelinSep 27, 2006
  12. Martin WaitzSep 27, 2006
  13. Linus TorvaldsSep 27, 2006
  14. Martin WaitzSep 28, 2006
  15. Junio C HamanoSep 28, 2006
  16. Andreas EricssonSep 29, 2006
  17. Johannes SchindelinSep 27, 2006
  18. SeanSep 27, 2006

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.