Merge branch 'zj/diff-stat-smaller-num-columns'
authorJunio C Hamano <gitster@pobox.com>
Wed, 2 May 2012 20:53:28 +0000 (13:53 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 May 2012 20:53:28 +0000 (13:53 -0700)
Spend only minimum number of columns necessary to show the number of lines
in the output from "diff --stat", instead of always allocating 4 columns
even when showing changes that are much smaller than 1000 lines.

By Zbigniew Jędrzejewski-Szmek
* zj/diff-stat-smaller-num-columns:
diff --stat: use less columns for change counts

1  2 
Documentation/gitcore-tutorial.txt
diff.c
t/t4052-stat-output.sh
index f5074a8976d8d743352e2d5d1305e32dbb1584e4,5b5d5a4c6c68c067e1ea7d3a6e98242c18af405a..9d893369a00b6a924876fb234c1082db2021abf3
@@@ -151,8 -151,8 +151,8 @@@ to your working tree, you use the 'git 
  program normally just takes a list of filenames you want to update, but
  to avoid trivial mistakes, it refuses to add new entries to the index
  (or remove existing ones) unless you explicitly tell it that you're
 -adding a new entry with the `\--add` flag (or removing an entry with the
 -`\--remove`) flag.
 +adding a new entry with the `--add` flag (or removing an entry with the
 +`--remove`) flag.
  
  So to populate the index with the two files you just created, you can do
  
@@@ -399,10 -399,10 +399,10 @@@ $ git diff HEA
  which ends up doing the above for you.
  
  In other words, 'git diff-index' normally compares a tree against the
 -working tree, but when given the `\--cached` flag, it is told to
 +working tree, but when given the `--cached` flag, it is told to
  instead compare against just the index cache contents, and ignore the
  current working tree state entirely. Since we just wrote the index
 -file to HEAD, doing `git diff-index \--cached -p HEAD` should thus return
 +file to HEAD, doing `git diff-index --cached -p HEAD` should thus return
  an empty set of differences, and that's exactly what it does.
  
  [NOTE]
  comparisons, and saying that it compares a tree against the working
  tree is thus not strictly accurate. In particular, the list of
  files to compare (the "meta-data") *always* comes from the index file,
 -regardless of whether the `\--cached` flag is used or not. The `\--cached`
 +regardless of whether the `--cached` flag is used or not. The `--cached`
  flag really only determines whether the file *contents* to be compared
  come from the working tree or not.
  
@@@ -433,7 -433,7 +433,7 @@@ update the index cache
  $ git update-index hello
  ------------------------------------------------
  
 -(note how we didn't need the `\--add` flag this time, since git knew
 +(note how we didn't need the `--add` flag this time, since git knew
  about the file already).
  
  Note what happens to the different 'git diff-{asterisk}' versions here.
@@@ -560,7 -560,7 +560,7 @@@ short history
  When using the above two commands, the initial commit will be shown.
  If this is a problem because it is huge, you can hide it by setting
  the log.showroot configuration variable to false. Having this, you
 -can still show it for each command just adding the `\--root` option,
 +can still show it for each command just adding the `--root` option,
  which is a flag for 'git diff-tree' accepted by both commands.
  
  With that, you should now be having some inkling of what git does, and
@@@ -881,7 -881,7 +881,7 @@@ helps you view what's going on
  $ gitk --all
  ----------------
  
 -will show you graphically both of your branches (that's what the `\--all`
 +will show you graphically both of your branches (that's what the `--all`
  means: normally it will just show you your current `HEAD`) and their
  histories. You can also see exactly how they came to be from a common
  source.
@@@ -935,7 -935,7 +935,7 @@@ which will very loudly warn you that yo
  (which is correct, so never mind), and you can write a small merge
  message about your adventures in 'git merge'-land.
  
 -After you're done, start up `gitk \--all` to see graphically what the
 +After you're done, start up `gitk --all` to see graphically what the
  history looks like. Notice that `mybranch` still exists, and you can
  switch to it, and continue to work with it if you want to. The
  `mybranch` branch will not contain the merge, but next time you merge it
@@@ -958,11 -958,11 +958,11 @@@ $ git show-branch --topo-order --more=
  The first two lines indicate that it is showing the two branches
  and the first line of the commit log message from their
  top-of-the-tree commits, you are currently on `master` branch
 -(notice the asterisk `{asterisk}` character), and the first column for
 +(notice the asterisk `*` character), and the first column for
  the later output lines is used to show commits contained in the
  `master` branch, and the second column for the `mybranch`
  branch. Three commits are shown along with their log messages.
 -All of them have non blank characters in the first column (`{asterisk}`
 +All of them have non blank characters in the first column (`*`
  shows an ordinary commit on the current branch, `-` is a merge commit), which
  means they are now part of the `master` branch. Only the "Some
  work" commit has the plus `+` character in the second column,
@@@ -1002,8 -1002,8 +1002,8 @@@ would be different
  ----------------
  Updating from ae3a2da... to a80b4aa....
  Fast-forward (no commit created; -m option ignored)
-  example |    1 +
-  hello   |    1 +
+  example | 1 +
+  hello   | 1 +
   2 files changed, 2 insertions(+)
  ----------------
  
@@@ -1013,7 -1013,7 +1013,7 @@@ not actually do a merge. Instead, it ju
  the tree of your branch to that of the `master` branch. This is
  often called 'fast-forward' merge.
  
 -You can run `gitk \--all` again to see how the commit ancestry
 +You can run `gitk --all` again to see how the commit ancestry
  looks like, or run 'show-branch', which tells you this.
  
  ------------------------------------------------
@@@ -1257,7 -1257,7 +1257,7 @@@ this 'collapsing' tends to trivially me
  fairly quickly, leaving only a handful of real changes in non-zero
  stages.
  
 -To look at only non-zero stages, use `\--unmerged` flag:
 +To look at only non-zero stages, use `--unmerged` flag:
  
  ------------
  $ git ls-files --unmerged
@@@ -1420,7 -1420,7 +1420,7 @@@ packed, and stores the packed file in `
  directory.
  
  [NOTE]
 -You will see two files, `pack-{asterisk}.pack` and `pack-{asterisk}.idx`,
 +You will see two files, `pack-*.pack` and `pack-*.idx`,
  in `.git/objects/pack` directory. They are closely related to
  each other, and if you ever copy them by hand to a different
  repository for whatever reason, you should make sure you copy
diff --combined diff.c
index 7da16c9590805dc687d7dc67acac2cb104144036,c316e0cbfbb788a6e0066069c3425b1f712e543b..02081d2af249d7fef660bd401a6d508b2e21cff1
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1443,8 -1443,8 +1443,8 @@@ static void show_stats(struct diffstat_
  {
        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 = 4, 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;
                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;
        }
         * 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.
         */
  
        if (options->stat_width == -1)
 -              width = term_columns();
 +              width = term_columns() - options->output_prefix_length;
        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;
  
        /*
         * 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 = (options->stat_graph_width &&
-                      options->stat_graph_width < max_change) ?
-               options->stat_graph_width : max_change;
+       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)
 +              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 (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, " -> ");
                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;
                }
  
                }
                fprintf(options->file, "%s", line_prefix);
                show_name(options->file, prefix, name, len);
-               fprintf(options->file, "%5"PRIuMAX"%s", added + deleted,
-                               added + deleted ? " " : "");
+               fprintf(options->file, " %*"PRIuMAX"%s",
+                       number_width, added + deleted,
+                       added + deleted ? " " : "");
                show_graph(options->file, '+', add, add_c, reset);
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
diff --combined t/t4052-stat-output.sh
index ddd94976c25584d4f8dca4265f10be967d7db378,4bdc7d43765352c9e6ab3c04f0432abbb55b8bf4..b68afefa3ce2bf8ad810cee2d6ab108d4f1219ba
@@@ -22,7 -22,7 +22,7 @@@ test_expect_success 'preparation' 
  while read cmd args
  do
        cat >expect <<-'EOF'
-        ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+        ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
        EOF
        test_expect_success "$cmd: small change with long name gives more space to the name" '
                git $cmd $args >output &&
@@@ -31,7 -31,7 +31,7 @@@
        '
  
        cat >expect <<-'EOF'
-        ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+        ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
        EOF
        test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" '
                git $cmd $args --stat=40 >output &&
@@@ -46,7 -46,7 +46,7 @@@
        '
  
        cat >expect <<-'EOF'
-        ...aaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+        ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
        EOF
        test_expect_success "$cmd --stat=...,name-width with long name" '
                git $cmd $args --stat=60,30 >output &&
@@@ -82,15 -82,11 +82,15 @@@ test_expect_success 'preparation for bi
  cat >expect80 <<'EOF'
   abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  EOF
 -
 +cat >expect80-graph <<'EOF'
 +|  abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +EOF
  cat >expect200 <<'EOF'
   abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  EOF
 -
 +cat >expect200-graph <<'EOF'
 +|  abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +EOF
  while read verb expect cmd args
  do
        test_expect_success "$cmd $verb COLUMNS (big change)" '
                grep " | " output >actual &&
                test_cmp "$expect" actual
        '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --graph $verb COLUMNS (big change)" '
 +              COLUMNS=200 git $cmd $args --graph >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect-graph" actual
 +      '
  done <<\EOF
  ignores expect80 format-patch -1 --stdout
  respects expect200 diff HEAD^ HEAD --stat
@@@ -116,9 -104,7 +116,9 @@@ EO
  cat >expect40 <<'EOF'
   abcd | 1000 ++++++++++++++++++++++++++
  EOF
 -
 +cat >expect40-graph <<'EOF'
 +|  abcd | 1000 ++++++++++++++++++++++++
 +EOF
  while read verb expect cmd args
  do
        test_expect_success "$cmd $verb not enough COLUMNS (big change)" '
                test_cmp "$expect" actual
        '
  
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --graph $verb not enough COLUMNS (big change)" '
 +              COLUMNS=40 git $cmd $args --graph >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect-graph" actual
 +      '
 +done <<\EOF
 +ignores expect80 format-patch -1 --stdout
 +respects expect40 diff HEAD^ HEAD --stat
 +respects expect40 show --stat
 +respects expect40 log -1 --stat
 +EOF
 +
 +cat >expect40 <<'EOF'
 + abcd | 1000 ++++++++++++++++++++++++++
 +EOF
 +cat >expect40-graph <<'EOF'
 +|  abcd | 1000 ++++++++++++++++++++++++++
 +EOF
 +while read verb expect cmd args
 +do
        test_expect_success "$cmd $verb statGraphWidth config" '
                git -c diff.statGraphWidth=26 $cmd $args >output
                grep " | " output >actual &&
                test_cmp "$expect" actual
        '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --graph $verb statGraphWidth config" '
 +              git -c diff.statGraphWidth=26 $cmd $args --graph >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect-graph" actual
 +      '
  done <<\EOF
  ignores expect80 format-patch -1 --stdout
  respects expect40 diff HEAD^ HEAD --stat
@@@ -173,9 -129,6 +173,9 @@@ EO
  cat >expect <<'EOF'
   abcd | 1000 ++++++++++++++++++++++++++
  EOF
 +cat >expect-graph <<'EOF'
 +|  abcd | 1000 ++++++++++++++++++++++++++
 +EOF
  while read cmd args
  do
        test_expect_success "$cmd --stat=width with big change" '
                test_cmp expect actual
        '
  
 -      test_expect_success "$cmd --stat-graph--width with big change" '
 +      test_expect_success "$cmd --stat-graph-width with big change" '
                git $cmd $args --stat-graph-width=26 >output
                grep " | " output >actual &&
                test_cmp expect actual
        '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --stat-width=width --graph with big change" '
 +              git $cmd $args --stat-width=40 --graph >output
 +              grep " | " output >actual &&
 +              test_cmp expect-graph actual
 +      '
 +
 +      test_expect_success "$cmd --stat-graph-width --graph with big change" '
 +              git $cmd $args --stat-graph-width=26 --graph >output
 +              grep " | " output >actual &&
 +              test_cmp expect-graph actual
 +      '
  done <<\EOF
  format-patch -1 --stdout
  diff HEAD^ HEAD --stat
@@@ -225,9 -164,6 +225,9 @@@ test_expect_success 'preparation for lo
  cat >expect <<'EOF'
   ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++
  EOF
 +cat >expect-graph <<'EOF'
 +|  ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++
 +EOF
  while read cmd args
  do
        test_expect_success "$cmd --stat=width with big change is more balanced" '
                grep " | " output >actual &&
                test_cmp expect actual
        '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --stat=width --graph with big change is balanced" '
 +              git $cmd $args --stat-width=60 --graph >output &&
 +              grep " | " output >actual &&
 +              test_cmp expect-graph actual
 +      '
  done <<\EOF
  format-patch -1 --stdout
  diff HEAD^ HEAD --stat
@@@ -253,15 -181,9 +253,15 @@@ EO
  cat >expect80 <<'EOF'
   ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++
  EOF
 +cat >expect80-graph <<'EOF'
 +|  ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++
 +EOF
  cat >expect200 <<'EOF'
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  EOF
 +cat >expect200-graph <<'EOF'
 +|  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +EOF
  while read verb expect cmd args
  do
        test_expect_success "$cmd $verb COLUMNS (long filename)" '
                grep " | " output >actual &&
                test_cmp "$expect" actual
        '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success "$cmd --graph $verb COLUMNS (long filename)" '
 +              COLUMNS=200 git $cmd $args --graph >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect-graph" actual
 +      '
  done <<\EOF
  ignores expect80 format-patch -1 --stdout
  respects expect200 diff HEAD^ HEAD --stat
@@@ -284,36 -198,6 +284,36 @@@ respects expect200 show --sta
  respects expect200 log -1 --stat
  EOF
  
 +cat >expect1 <<'EOF'
 + ...aaaaaaa | 1000 ++++++
 +EOF
 +cat >expect1-graph <<'EOF'
 +|  ...aaaaaaa | 1000 ++++++
 +EOF
 +while read verb expect cmd args
 +do
 +      test_expect_success COLUMNS_CAN_BE_1 \
 +              "$cmd $verb prefix greater than COLUMNS (big change)" '
 +              COLUMNS=1 git $cmd $args >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect" actual
 +      '
 +
 +      test "$cmd" != diff || continue
 +
 +      test_expect_success COLUMNS_CAN_BE_1 \
 +              "$cmd --graph $verb prefix greater than COLUMNS (big change)" '
 +              COLUMNS=1 git $cmd $args --graph >output
 +              grep " | " output >actual &&
 +              test_cmp "$expect-graph" actual
 +      '
 +done <<\EOF
 +ignores expect80 format-patch -1 --stdout
 +respects expect1 diff HEAD^ HEAD --stat
 +respects expect1 show --stat
 +respects expect1 log -1 --stat
 +EOF
 +
  cat >expect <<'EOF'
   abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  EOF