Code

Merge branch 'jc/diff-stat-scaler' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Feb 2012 23:00:33 +0000 (15:00 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Feb 2012 23:00:33 +0000 (15:00 -0800)
* jc/diff-stat-scaler:
  diff --stat: show bars of same length for paths with same amount of changes

1  2 
diff.c

diff --combined diff.c
index 84780fd5e641d9f1042f82863d1290f7ad8d92b5,74db18846f3149822bb1cd9b988feb953cc309dd..05d0814e276601239d122767e635a37bc294e05f
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1113,15 -1113,6 +1113,15 @@@ static void fn_out_consume(void *priv, 
                        diff_words_append(line, len,
                                          &ecbdata->diff_words->plus);
                        return;
 +              } else if (!prefixcmp(line, "\\ ")) {
 +                      /*
 +                       * Eat the "no newline at eof" marker as if we
 +                       * saw a "+" or "-" line with nothing on it,
 +                       * and return without diff_words_flush() to
 +                       * defer processing. If this is the end of
 +                       * preimage, more "+" lines may come after it.
 +                       */
 +                      return;
                }
                diff_words_flush(ecbdata);
                if (ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) {
@@@ -1276,13 -1267,15 +1276,15 @@@ const char mime_boundary_leader[] = "--
  
  static int scale_linear(int it, int width, int max_change)
  {
+       if (!it)
+               return 0;
        /*
-        * make sure that at least one '-' is printed if there were deletions,
-        * and likewise for '+'.
+        * make sure that at least one '-' or '+' is printed if
+        * there is any change to this path. The easiest way is to
+        * scale linearly as if the alloted width is one column shorter
+        * than it is, and then add 1 to the result.
         */
-       if (max_change < 2)
-               return it;
-       return ((it - 1) * (width - 1) + max_change - 1) / (max_change - 1);
+       return 1 + (it * (width - 1) / max_change);
  }
  
  static void show_name(FILE *file,
@@@ -1322,55 -1315,6 +1324,55 @@@ static void fill_print_name(struct diff
        file->print_name = pname;
  }
  
 +int print_stat_summary(FILE *fp, int files, int insertions, int deletions)
 +{
 +      struct strbuf sb = STRBUF_INIT;
 +      int ret;
 +
 +      if (!files) {
 +              assert(insertions == 0 && deletions == 0);
 +              return fputs(_(" 0 files changed\n"), fp);
 +      }
 +
 +      strbuf_addf(&sb,
 +                  Q_(" %d file changed", " %d files changed", files),
 +                  files);
 +
 +      /*
 +       * For binary diff, the caller may want to print "x files
 +       * changed" with insertions == 0 && deletions == 0.
 +       *
 +       * Not omitting "0 insertions(+), 0 deletions(-)" in this case
 +       * is probably less confusing (i.e skip over "2 files changed
 +       * but nothing about added/removed lines? Is this a bug in Git?").
 +       */
 +      if (insertions || deletions == 0) {
 +              /*
 +               * TRANSLATORS: "+" in (+) is a line addition marker;
 +               * do not translate it.
 +               */
 +              strbuf_addf(&sb,
 +                          Q_(", %d insertion(+)", ", %d insertions(+)",
 +                             insertions),
 +                          insertions);
 +      }
 +
 +      if (deletions || insertions == 0) {
 +              /*
 +               * TRANSLATORS: "-" in (-) is a line removal marker;
 +               * do not translate it.
 +               */
 +              strbuf_addf(&sb,
 +                          Q_(", %d deletion(-)", ", %d deletions(-)",
 +                             deletions),
 +                          deletions);
 +      }
 +      strbuf_addch(&sb, '\n');
 +      ret = fputs(sb.buf, fp);
 +      strbuf_release(&sb);
 +      return ret;
 +}
 +
  static void show_stats(struct diffstat_t *data, struct diff_options *options)
  {
        int i, len, add, del, adds = 0, dels = 0;
                dels += del;
  
                if (width <= max_change) {
-                       add = scale_linear(add, width, max_change);
-                       del = scale_linear(del, width, max_change);
+                       int total = add + del;
+                       total = scale_linear(add + del, width, max_change);
+                       if (total < 2 && add && del)
+                               /* width >= 2 due to the sanity check */
+                               total = 2;
+                       if (add < del) {
+                               add = scale_linear(add, width, max_change);
+                               del = total - add;
+                       } else {
+                               del = scale_linear(del, width, max_change);
+                               add = total - del;
+                       }
                }
                fprintf(options->file, "%s", line_prefix);
                show_name(options->file, prefix, name, len);
                extra_shown = 1;
        }
        fprintf(options->file, "%s", line_prefix);
 -      fprintf(options->file,
 -             " %d files changed, %d insertions(+), %d deletions(-)\n",
 -             total_files, adds, dels);
 +      print_stat_summary(options->file, total_files, adds, dels);
  }
  
  static void show_shortstats(struct diffstat_t *data, struct diff_options *options)
                                options->output_prefix_data);
                fprintf(options->file, "%s", msg->buf);
        }
 -      fprintf(options->file, " %d files changed, %d insertions(+), %d deletions(-)\n",
 -             total_files, adds, dels);
 +      print_stat_summary(options->file, total_files, adds, dels);
  }
  
  static void show_numstat(struct diffstat_t *data, struct diff_options *options)