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@xxxxxxx> --- * 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 - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html