Merge branch 'tr/maint-word-diff-incomplete-line'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Jan 2012 23:16:19 +0000 (15:16 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Jan 2012 23:16:19 +0000 (15:16 -0800)
* tr/maint-word-diff-incomplete-line:
word-diff: ignore '\ No newline at eof' marker

1  2 
diff.c
t/t4034-diff-words.sh
diff --combined diff.c
index 374ecf3b486e218c52f94ba14481a715c19b80db,2e6965e84b8d87f46081f8b26b9d3fa8554c4049..7e154265f778c645192cbf17c65b9bea2a507402
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -137,7 -137,7 +137,7 @@@ static int git_config_rename(const cha
  int git_diff_ui_config(const char *var, const char *value, void *cb)
  {
        if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
 -              diff_use_color_default = git_config_colorbool(var, value, -1);
 +              diff_use_color_default = git_config_colorbool(var, value);
                return 0;
        }
        if (!strcmp(var, "diff.renames")) {
        if (!strcmp(var, "diff.ignoresubmodules"))
                handle_ignore_submodules_arg(&default_diff_options, value);
  
 +      if (git_color_config(var, value, cb) < 0)
 +              return -1;
 +
        return git_diff_basic_config(var, value, cb);
  }
  
@@@ -215,7 -212,7 +215,7 @@@ int git_diff_basic_config(const char *v
        if (!prefixcmp(var, "submodule."))
                return parse_submodule_config_option(var, value);
  
 -      return git_color_default_config(var, value, cb);
 +      return git_default_config(var, value, cb);
  }
  
  static char *quote_two(const char *one, const char *two)
@@@ -586,10 -583,11 +586,10 @@@ static void emit_rewrite_diff(const cha
                              struct diff_options *o)
  {
        int lc_a, lc_b;
 -      int color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
        const char *name_a_tab, *name_b_tab;
 -      const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
 -      const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
 -      const char *reset = diff_get_color(color_diff, DIFF_RESET);
 +      const char *metainfo = diff_get_color(o->use_color, DIFF_METAINFO);
 +      const char *fraginfo = diff_get_color(o->use_color, DIFF_FRAGINFO);
 +      const char *reset = diff_get_color(o->use_color, DIFF_RESET);
        static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
        const char *a_prefix, *b_prefix;
        char *data_one, *data_two;
        size_two = fill_textconv(textconv_two, two, &data_two);
  
        memset(&ecbdata, 0, sizeof(ecbdata));
 -      ecbdata.color_diff = color_diff;
 +      ecbdata.color_diff = want_color(o->use_color);
        ecbdata.found_changesp = &o->found_changes;
        ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
        ecbdata.opt = o;
@@@ -1006,7 -1004,7 +1006,7 @@@ static void free_diff_words_data(struc
  
  const char *diff_get_color(int diff_use_color, enum color_diff ix)
  {
 -      if (diff_use_color)
 +      if (want_color(diff_use_color))
                return diff_colors[ix];
        return "";
  }
@@@ -1113,6 -1111,15 +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) {
@@@ -1318,10 -1325,9 +1327,10 @@@ 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;
 +      int width, name_width, count;
        const char *reset, *add_c, *del_c;
        const char *line_prefix = "";
 +      int extra_shown = 0;
        struct strbuf *msg = NULL;
  
        if (data->nr == 0)
  
        width = options->stat_width ? options->stat_width : 80;
        name_width = options->stat_name_width ? options->stat_name_width : 50;
 +      count = options->stat_count ? options->stat_count : data->nr;
  
        /* Sanity: give at least 5 columns to the graph,
         * but leave at least 10 columns for the name.
        add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
        del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
  
 -      for (i = 0; i < data->nr; i++) {
 +      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 &&
 +                       (change == 0)) {
 +                      count++; /* not shown == room for one more */
 +                      continue;
 +              }
                fill_print_name(file);
                len = strlen(file->print_name);
                if (max_len < len)
                if (max_change < change)
                        max_change = change;
        }
 +      count = i; /* min(count, data->nr) */
  
        /* Compute the width of the graph part;
         * 10 is for one blank at the beginning of the line plus
        else
                width = max_change;
  
 -      for (i = 0; i < data->nr; i++) {
 +      for (i = 0; i < count; i++) {
                const char *prefix = "";
                char *name = data->files[i]->print_name;
                uintmax_t added = data->files[i]->added;
                uintmax_t deleted = data->files[i]->deleted;
                int name_len;
  
 +              if (!data->files[i]->is_renamed &&
 +                       (added + deleted == 0)) {
 +                      total_files--;
 +                      continue;
 +              }
                /*
                 * "scale" the filename
                 */
                        fprintf(options->file, "  Unmerged\n");
                        continue;
                }
 -              else if (!data->files[i]->is_renamed &&
 -                       (added + deleted == 0)) {
 -                      total_files--;
 -                      continue;
 -              }
  
                /*
                 * scale the add/delete
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
        }
 +      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 &&
 +                       (added + deleted == 0)) {
 +                      total_files--;
 +                      continue;
 +              }
 +              adds += added;
 +              dels += deleted;
 +              if (!extra_shown)
 +                      fprintf(options->file, "%s ...\n", line_prefix);
 +              extra_shown = 1;
 +      }
        fprintf(options->file, "%s", line_prefix);
        fprintf(options->file,
               " %d files changed, %d insertions(+), %d deletions(-)\n",
@@@ -1810,10 -1795,11 +1819,10 @@@ static int is_conflict_marker(const cha
  static void checkdiff_consume(void *priv, char *line, unsigned long len)
  {
        struct checkdiff_t *data = priv;
 -      int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF);
        int marker_size = data->conflict_marker_size;
 -      const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE);
 -      const char *reset = diff_get_color(color_diff, DIFF_RESET);
 -      const char *set = diff_get_color(color_diff, DIFF_FILE_NEW);
 +      const char *ws = diff_get_color(data->o->use_color, DIFF_WHITESPACE);
 +      const char *reset = diff_get_color(data->o->use_color, DIFF_RESET);
 +      const char *set = diff_get_color(data->o->use_color, DIFF_FILE_NEW);
        char *err;
        char *line_prefix = "";
        struct strbuf *msgbuf;
@@@ -2158,7 -2144,7 +2167,7 @@@ static void builtin_diff(const char *na
                memset(&xecfg, 0, sizeof(xecfg));
                memset(&ecbdata, 0, sizeof(ecbdata));
                ecbdata.label_path = lbl;
 -              ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
 +              ecbdata.color_diff = want_color(o->use_color);
                ecbdata.found_changesp = &o->found_changes;
                ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
                if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
 +              if (DIFF_OPT_TST(o, FUNCCONTEXT))
 +                      xecfg.flags |= XDL_EMIT_FUNCCONTEXT;
                if (pe)
                        xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
                if (!diffopts)
                                        break;
                                }
                        }
 -                      if (DIFF_OPT_TST(o, COLOR_DIFF)) {
 +                      if (want_color(o->use_color)) {
                                struct diff_words_style *st = ecbdata.diff_words->style;
                                st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
                                st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
@@@ -2276,8 -2260,6 +2285,8 @@@ static void builtin_diffstat(const cha
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = o->xdl_opts;
 +              xecfg.ctxlen = o->context;
 +              xecfg.interhunkctxlen = o->interhunkcontext;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
                              &xpp, &xecfg);
        }
@@@ -2860,7 -2842,7 +2869,7 @@@ static void run_diff_cmd(const char *pg
                 */
                fill_metainfo(msg, name, other, one, two, o, p,
                              &must_show_header,
 -                            DIFF_OPT_TST(o, COLOR_DIFF) && !pgm);
 +                            want_color(o->use_color) && !pgm);
                xfrm_msg = msg->len ? msg->buf : NULL;
        }
  
@@@ -3026,7 -3008,8 +3035,7 @@@ void diff_setup(struct diff_options *op
  
        options->change = diff_change;
        options->add_remove = diff_addremove;
 -      if (diff_use_color_default > 0)
 -              DIFF_OPT_SET(options, COLOR_DIFF);
 +      options->use_color = diff_use_color_default;
        options->detect_rename = diff_detect_rename_default;
  
        if (diff_no_prefix) {
@@@ -3234,7 -3217,6 +3243,7 @@@ static int stat_opt(struct diff_option
        char *end;
        int width = options->stat_width;
        int name_width = options->stat_name_width;
 +      int count = options->stat_count;
        int argcount = 1;
  
        arg += strlen("--stat");
                                name_width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
 +              } else if (!prefixcmp(arg, "-count")) {
 +                      arg += strlen("-count");
 +                      if (*arg == '=')
 +                              count = strtoul(arg + 1, &end, 10);
 +                      else if (!*arg && !av[1])
 +                              die("Option '--stat-count' requires a value");
 +                      else if (!*arg) {
 +                              count = strtoul(av[1], &end, 10);
 +                              argcount = 2;
 +                      }
                }
                break;
        case '=':
                width = strtoul(arg+1, &end, 10);
                if (*end == ',')
                        name_width = strtoul(end+1, &end, 10);
 +              if (*end == ',')
 +                      count = strtoul(end+1, &end, 10);
        }
  
        /* Important! This checks all the error cases! */
        options->output_format |= DIFF_FORMAT_DIFFSTAT;
        options->stat_name_width = name_width;
        options->stat_width = width;
 +      options->stat_count = count;
        return argcount;
  }
  
@@@ -3353,7 -3322,7 +3362,7 @@@ int diff_opt_parse(struct diff_options 
        else if (!strcmp(arg, "-s"))
                options->output_format |= DIFF_FORMAT_NO_OUTPUT;
        else if (!prefixcmp(arg, "--stat"))
 -              /* --stat, --stat-width, or --stat-name-width */
 +              /* --stat, --stat-width, --stat-name-width, or --stat-count */
                return stat_opt(options, av);
  
        /* renames options */
        }
  
        /* xdiff options */
 +      else if (!strcmp(arg, "--minimal"))
 +              DIFF_XDL_SET(options, NEED_MINIMAL);
 +      else if (!strcmp(arg, "--no-minimal"))
 +              DIFF_XDL_CLR(options, NEED_MINIMAL);
        else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
                DIFF_XDL_SET(options, IGNORE_WHITESPACE);
        else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
                DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
        else if (!strcmp(arg, "--patience"))
                DIFF_XDL_SET(options, PATIENCE_DIFF);
 +      else if (!strcmp(arg, "--histogram"))
 +              DIFF_XDL_SET(options, HISTOGRAM_DIFF);
  
        /* flags options */
        else if (!strcmp(arg, "--binary")) {
        else if (!strcmp(arg, "--follow"))
                DIFF_OPT_SET(options, FOLLOW_RENAMES);
        else if (!strcmp(arg, "--color"))
 -              DIFF_OPT_SET(options, COLOR_DIFF);
 +              options->use_color = 1;
        else if (!prefixcmp(arg, "--color=")) {
 -              int value = git_config_colorbool(NULL, arg+8, -1);
 -              if (value == 0)
 -                      DIFF_OPT_CLR(options, COLOR_DIFF);
 -              else if (value > 0)
 -                      DIFF_OPT_SET(options, COLOR_DIFF);
 -              else
 +              int value = git_config_colorbool(NULL, arg+8);
 +              if (value < 0)
                        return error("option `color' expects \"always\", \"auto\", or \"never\"");
 +              options->use_color = value;
        }
        else if (!strcmp(arg, "--no-color"))
 -              DIFF_OPT_CLR(options, COLOR_DIFF);
 +              options->use_color = 0;
        else if (!strcmp(arg, "--color-words")) {
 -              DIFF_OPT_SET(options, COLOR_DIFF);
 +              options->use_color = 1;
                options->word_diff = DIFF_WORDS_COLOR;
        }
        else if (!prefixcmp(arg, "--color-words=")) {
 -              DIFF_OPT_SET(options, COLOR_DIFF);
 +              options->use_color = 1;
                options->word_diff = DIFF_WORDS_COLOR;
                options->word_regex = arg + 14;
        }
                if (!strcmp(type, "plain"))
                        options->word_diff = DIFF_WORDS_PLAIN;
                else if (!strcmp(type, "color")) {
 -                      DIFF_OPT_SET(options, COLOR_DIFF);
 +                      options->use_color = 1;
                        options->word_diff = DIFF_WORDS_COLOR;
                }
                else if (!strcmp(type, "porcelain"))
        else if (opt_arg(arg, '\0', "inter-hunk-context",
                         &options->interhunkcontext))
                ;
 +      else if (!strcmp(arg, "-W"))
 +              DIFF_OPT_SET(options, FUNCCONTEXT);
 +      else if (!strcmp(arg, "--function-context"))
 +              DIFF_OPT_SET(options, FUNCCONTEXT);
 +      else if (!strcmp(arg, "--no-function-context"))
 +              DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
                options->file = fopen(optarg, "w");
                if (!options->file)
diff --combined t/t4034-diff-words.sh
index 6f1e5a2a15f0215e4ed7c19437f5d000edbbd255,219b45e9a49654fde2db6f2e8b4326beccee1da7..5c2012111c28d338ad979fb7bcca871e744184fe
@@@ -299,7 -299,6 +299,7 @@@ test_language_driver cshar
  test_language_driver fortran
  test_language_driver html
  test_language_driver java
 +test_language_driver matlab
  test_language_driver objc
  test_language_driver pascal
  test_language_driver perl
@@@ -334,4 -333,18 +334,18 @@@ test_expect_success 'word-diff with dif
        word_diff --word-diff=plain
  '
  
+ test_expect_success 'word-diff with no newline at EOF' '
+       cat >expect <<-\EOF &&
+       diff --git a/pre b/post
+       index 7bf316e..3dd0303 100644
+       --- a/pre
+       +++ b/post
+       @@ -1 +1 @@
+       a a [-a-]{+ab+} a a
+       EOF
+       printf "%s" "a a a a a" >pre &&
+       printf "%s" "a a ab a a" >post &&
+       word_diff --word-diff=plain
+ '
  test_done