]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'lt/diff-stat-show-0-lines'
authorJunio C Hamano <gitster@pobox.com>
Mon, 26 Nov 2012 02:44:06 +0000 (18:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 26 Nov 2012 02:44:06 +0000 (18:44 -0800)
We failed to mention a file without any content change but whose
permission bit was modified, or (worse yet) a new file without any
content in the "git diff --stat" output.

* lt/diff-stat-show-0-lines:
  Fix "git diff --stat" for interesting - but empty - file changes

1  2 
diff.c

diff --combined diff.c
index e89a2015eb794616416cd02a8f87695efc28d4bd,95bbad66c68661cf4c543fc1b4e7216d4e3d8806..71b13878523dca95c8b49712ea245fda1e8b8b3b
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -15,7 -15,6 +15,7 @@@
  #include "sigchain.h"
  #include "submodule.h"
  #include "ll-merge.h"
 +#include "string-list.h"
  
  #ifdef NO_FAST_WORKING_DIRECTORY
  #define FAST_WORKING_DIRECTORY 0
@@@ -27,7 -26,6 +27,7 @@@ static int diff_detect_rename_default
  static int diff_rename_limit_default = 400;
  static int diff_suppress_blank_empty;
  static int diff_use_color_default = -1;
 +static int diff_context_default = 3;
  static const char *diff_word_regex_cfg;
  static const char *external_diff_cmd_cfg;
  int diff_auto_refresh_index = 1;
@@@ -70,30 -68,26 +70,30 @@@ static int parse_diff_color_slot(const 
        return -1;
  }
  
 -static int parse_dirstat_params(struct diff_options *options, const char *params,
 +static int parse_dirstat_params(struct diff_options *options, const char *params_string,
                                struct strbuf *errmsg)
  {
 -      const char *p = params;
 -      int p_len, ret = 0;
 +      char *params_copy = xstrdup(params_string);
 +      struct string_list params = STRING_LIST_INIT_NODUP;
 +      int ret = 0;
 +      int i;
  
 -      while (*p) {
 -              p_len = strchrnul(p, ',') - p;
 -              if (!memcmp(p, "changes", p_len)) {
 +      if (*params_copy)
 +              string_list_split_in_place(&params, params_copy, ',', -1);
 +      for (i = 0; i < params.nr; i++) {
 +              const char *p = params.items[i].string;
 +              if (!strcmp(p, "changes")) {
                        DIFF_OPT_CLR(options, DIRSTAT_BY_LINE);
                        DIFF_OPT_CLR(options, DIRSTAT_BY_FILE);
 -              } else if (!memcmp(p, "lines", p_len)) {
 +              } else if (!strcmp(p, "lines")) {
                        DIFF_OPT_SET(options, DIRSTAT_BY_LINE);
                        DIFF_OPT_CLR(options, DIRSTAT_BY_FILE);
 -              } else if (!memcmp(p, "files", p_len)) {
 +              } else if (!strcmp(p, "files")) {
                        DIFF_OPT_CLR(options, DIRSTAT_BY_LINE);
                        DIFF_OPT_SET(options, DIRSTAT_BY_FILE);
 -              } else if (!memcmp(p, "noncumulative", p_len)) {
 +              } else if (!strcmp(p, "noncumulative")) {
                        DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
 -              } else if (!memcmp(p, "cumulative", p_len)) {
 +              } else if (!strcmp(p, "cumulative")) {
                        DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
                } else if (isdigit(*p)) {
                        char *end;
                                while (isdigit(*++end))
                                        ; /* nothing */
                        }
 -                      if (end - p == p_len)
 +                      if (!*end)
                                options->dirstat_permille = permille;
                        else {
 -                              strbuf_addf(errmsg, _("  Failed to parse dirstat cut-off percentage '%.*s'\n"),
 -                                          p_len, p);
 +                              strbuf_addf(errmsg, _("  Failed to parse dirstat cut-off percentage '%s'\n"),
 +                                          p);
                                ret++;
                        }
                } else {
 -                      strbuf_addf(errmsg, _("  Unknown dirstat parameter '%.*s'\n"),
 -                                  p_len, p);
 +                      strbuf_addf(errmsg, _("  Unknown dirstat parameter '%s'\n"), p);
                        ret++;
                }
  
 -              p += p_len;
 -
 -              if (*p)
 -                      p++; /* more parameters, swallow separator */
        }
 +      string_list_clear(&params, 0);
 +      free(params_copy);
        return ret;
  }
  
@@@ -144,12 -141,6 +144,12 @@@ int git_diff_ui_config(const char *var
                diff_use_color_default = git_config_colorbool(var, value);
                return 0;
        }
 +      if (!strcmp(var, "diff.context")) {
 +              diff_context_default = git_config_int(var, value);
 +              if (diff_context_default < 0)
 +                      return -1;
 +              return 0;
 +      }
        if (!strcmp(var, "diff.renames")) {
                diff_detect_rename_default = git_config_rename(var, value);
                return 0;
@@@ -1309,6 -1300,7 +1309,7 @@@ struct diffstat_t 
                unsigned is_unmerged:1;
                unsigned is_binary:1;
                unsigned is_renamed:1;
+               unsigned is_interesting:1;
                uintmax_t added, deleted;
        } **files;
  };
@@@ -1478,7 -1470,7 +1479,7 @@@ static void show_stats(struct diffstat_
        for (i = 0; (i < count) && (i < data->nr); i++) {
                struct diffstat_file *file = data->files[i];
                uintmax_t change = file->added + file->deleted;
-               if (!data->files[i]->is_renamed &&
+               if (!data->files[i]->is_interesting &&
                         (change == 0)) {
                        count++; /* not shown == room for one more */
                        continue;
                uintmax_t deleted = data->files[i]->deleted;
                int name_len;
  
-               if (!data->files[i]->is_renamed &&
+               if (!data->files[i]->is_interesting &&
                         (added + deleted == 0)) {
                        total_files--;
                        continue;
        for (i = count; i < data->nr; i++) {
                uintmax_t added = data->files[i]->added;
                uintmax_t deleted = data->files[i]->deleted;
-               if (!data->files[i]->is_renamed &&
+               if (!data->files[i]->is_interesting &&
                         (added + deleted == 0)) {
                        total_files--;
                        continue;
@@@ -1706,7 -1698,7 +1707,7 @@@ static void show_shortstats(struct diff
  
                if (data->files[i]->is_unmerged)
                        continue;
-               if (!data->files[i]->is_renamed && (added + deleted == 0)) {
+               if (!data->files[i]->is_interesting && (added + deleted == 0)) {
                        total_files--;
                } else if (!data->files[i]->is_binary) { /* don't count bytes */
                        adds += added;
@@@ -2406,13 -2398,20 +2407,20 @@@ static void builtin_diffstat(const cha
                             struct diff_filespec *two,
                             struct diffstat_t *diffstat,
                             struct diff_options *o,
-                            int complete_rewrite)
+                            struct diff_filepair *p)
  {
        mmfile_t mf1, mf2;
        struct diffstat_file *data;
        int same_contents;
+       int complete_rewrite = 0;
+       if (!DIFF_PAIR_UNMERGED(p)) {
+               if (p->status == DIFF_STATUS_MODIFIED && p->score)
+                       complete_rewrite = 1;
+       }
  
        data = diffstat_add(diffstat, name_a, name_b);
+       data->is_interesting = p->status != 0;
  
        if (!one || !two) {
                data->is_unmerged = 1;
@@@ -3123,11 -3122,10 +3131,10 @@@ static void run_diffstat(struct diff_fi
  {
        const char *name;
        const char *other;
-       int complete_rewrite = 0;
  
        if (DIFF_PAIR_UNMERGED(p)) {
                /* unmerged */
-               builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
+               builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, p);
                return;
        }
  
        diff_fill_sha1_info(p->one);
        diff_fill_sha1_info(p->two);
  
-       if (p->status == DIFF_STATUS_MODIFIED && p->score)
-               complete_rewrite = 1;
-       builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
+       builtin_diffstat(name, other, p->one, p->two, diffstat, o, p);
  }
  
  static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
@@@ -3179,7 -3175,7 +3184,7 @@@ void diff_setup(struct diff_options *op
        options->break_opt = -1;
        options->rename_limit = -1;
        options->dirstat_permille = diff_dirstat_permille_default;
 -      options->context = 3;
 +      options->context = diff_context_default;
        DIFF_OPT_SET(options, RENAME_EMPTY);
  
        options->change = diff_change;
@@@ -4880,19 -4876,3 +4885,19 @@@ size_t fill_textconv(struct userdiff_dr
  
        return size;
  }
 +
 +void setup_diff_pager(struct diff_options *opt)
 +{
 +      /*
 +       * If the user asked for our exit code, then either they want --quiet
 +       * or --exit-code. We should definitely not bother with a pager in the
 +       * former case, as we will generate no output. Since we still properly
 +       * report our exit code even when a pager is run, we _could_ run a
 +       * pager with --exit-code. But since we have not done so historically,
 +       * and because it is easy to find people oneline advising "git diff
 +       * --exit-code" in hooks and other scripts, we do not do so.
 +       */
 +      if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&
 +          check_pager_config("diff") != 0)
 +              setup_pager();
 +}