Merge branch 'cc/maint-diff-CC-binary' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 22 Jun 2010 16:04:14 +0000 (09:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 22 Jun 2010 16:27:07 +0000 (09:27 -0700)
* cc/maint-diff-CC-binary:
  diff: fix "git show -C -C" output when renaming a binary file

Conflicts:
diff.c

1  2 
diff.c

diff --combined diff.c
index 230c310952f0296d195c32fbe18b26b279b3fd54,426fd046652bdfd82ec0ce399446acecb1a5ba49..57e1212fbcc9783d3fdbd248762247d8e0efd886
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -551,10 -551,6 +551,10 @@@ static void emit_rewrite_diff(const cha
                emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
        if (lc_b)
                emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
 +      if (textconv_one)
 +              free((char *)data_one);
 +      if (textconv_two)
 +              free((char *)data_two);
  }
  
  struct diff_words_buffer {
@@@ -717,7 -713,7 +717,7 @@@ static void diff_words_show(struct diff
        memset(&xecfg, 0, sizeof(xecfg));
        diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex);
        diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex);
 -      xpp.flags = XDF_NEED_MINIMAL;
 +      xpp.flags = 0;
        /* as only the hunk header will be parsed, we need a 0-context */
        xecfg.ctxlen = 0;
        xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
@@@ -1600,6 -1596,7 +1600,7 @@@ static void builtin_diff(const char *na
                         struct diff_filespec *one,
                         struct diff_filespec *two,
                         const char *xfrm_msg,
+                        int must_show_header,
                         struct diff_options *o,
                         int complete_rewrite)
  {
        if (lbl[0][0] == '/') {
                /* /dev/null */
                strbuf_addf(&header, "%snew file mode %06o%s\n", set, two->mode, reset);
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
+               must_show_header = 1;
        }
        else if (lbl[1][0] == '/') {
                strbuf_addf(&header, "%sdeleted file mode %06o%s\n", set, one->mode, reset);
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
+               must_show_header = 1;
        }
        else {
                if (one->mode != two->mode) {
                        strbuf_addf(&header, "%sold mode %06o%s\n", set, one->mode, reset);
                        strbuf_addf(&header, "%snew mode %06o%s\n", set, two->mode, reset);
+                       must_show_header = 1;
                }
 -              if (xfrm_msg && xfrm_msg[0])
 -                      strbuf_addf(&header, "%s%s%s\n", set, xfrm_msg, reset);
 +              if (xfrm_msg)
 +                      strbuf_addstr(&header, xfrm_msg);
  
                /*
                 * we do not run diff between different kind
              (diff_filespec_is_binary(two) && !textconv_two) )) {
                /* Quite common confusing case */
                if (mf1.size == mf2.size &&
-                   !memcmp(mf1.ptr, mf2.ptr, mf1.size))
+                   !memcmp(mf1.ptr, mf2.ptr, mf1.size)) {
+                       if (must_show_header)
+                               fprintf(o->file, "%s", header.buf);
                        goto free_ab_and_return;
+               }
                fprintf(o->file, "%s", header.buf);
                strbuf_reset(&header);
                if (DIFF_OPT_TST(o, BINARY))
                struct emit_callback ecbdata;
                const struct userdiff_funcname *pe;
  
-               if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS)) {
+               if (!DIFF_XDL_TST(o, WHITESPACE_FLAGS) || must_show_header) {
                        fprintf(o->file, "%s", header.buf);
                        strbuf_reset(&header);
                }
                        check_blank_at_eof(&mf1, &mf2, &ecbdata);
                ecbdata.file = o->file;
                ecbdata.header = header.len ? &header : NULL;
 -              xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 +              xpp.flags = o->xdl_opts;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
@@@ -1834,7 -1837,7 +1841,7 @@@ static void builtin_diffstat(const cha
  
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
 -              xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 +              xpp.flags = o->xdl_opts;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
                              &xpp, &xecfg);
        }
@@@ -1882,7 -1885,7 +1889,7 @@@ static void builtin_checkdiff(const cha
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
 -              xpp.flags = XDF_NEED_MINIMAL;
 +              xpp.flags = 0;
                xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
                              &xpp, &xecfg);
  
@@@ -2033,7 -2036,7 +2040,7 @@@ static int diff_populate_gitlink(struc
        char *data = xmalloc(100), *dirty = "";
  
        /* Are we looking at the work tree? */
 -      if (!s->sha1_valid && s->dirty_submodule)
 +      if (s->dirty_submodule)
                dirty = "-dirty";
  
        len = snprintf(data, 100,
@@@ -2320,41 -2323,37 +2327,42 @@@ static void fill_metainfo(struct strbu
                          struct diff_filespec *two,
                          struct diff_options *o,
                          struct diff_filepair *p,
 -                        int *must_show_header)
++                        int *must_show_header,
 +                        int use_color)
  {
 +      const char *set = diff_get_color(use_color, DIFF_METAINFO);
 +      const char *reset = diff_get_color(use_color, DIFF_RESET);
 +
+       *must_show_header = 1;
        strbuf_init(msg, PATH_MAX * 2 + 300);
        switch (p->status) {
        case DIFF_STATUS_COPIED:
 -              strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
 -              strbuf_addstr(msg, "\ncopy from ");
 +              strbuf_addf(msg, "%ssimilarity index %d%%",
 +                          set, similarity_index(p));
 +              strbuf_addf(msg, "%s\n%scopy from ", reset, set);
                quote_c_style(name, msg, NULL, 0);
 -              strbuf_addstr(msg, "\ncopy to ");
 +              strbuf_addf(msg, "%s\n%scopy to ", reset, set);
                quote_c_style(other, msg, NULL, 0);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
                break;
        case DIFF_STATUS_RENAMED:
 -              strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
 -              strbuf_addstr(msg, "\nrename from ");
 +              strbuf_addf(msg, "%ssimilarity index %d%%",
 +                          set, similarity_index(p));
 +              strbuf_addf(msg, "%s\n%srename from ", reset, set);
                quote_c_style(name, msg, NULL, 0);
 -              strbuf_addstr(msg, "\nrename to ");
 +              strbuf_addf(msg, "%s\n%srename to ", reset, set);
                quote_c_style(other, msg, NULL, 0);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
                break;
        case DIFF_STATUS_MODIFIED:
                if (p->score) {
 -                      strbuf_addf(msg, "dissimilarity index %d%%\n",
 -                                  similarity_index(p));
 +                      strbuf_addf(msg, "%sdissimilarity index %d%%%s\n",
 +                                  set, similarity_index(p), reset);
                        break;
                }
                /* fallthru */
        default:
--              /* nothing */
-               ;
+               *must_show_header = 0;
        }
        if (one && two && hashcmp(one->sha1, two->sha1)) {
                int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
                            (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
                                abbrev = 40;
                }
 -              strbuf_addf(msg, "index %.*s..%.*s",
 +              strbuf_addf(msg, "%sindex %.*s..%.*s", set,
                            abbrev, sha1_to_hex(one->sha1),
                            abbrev, sha1_to_hex(two->sha1));
                if (one->mode == two->mode)
                        strbuf_addf(msg, " %06o", one->mode);
 -              strbuf_addch(msg, '\n');
 +              strbuf_addf(msg, "%s\n", reset);
        }
 -      if (msg->len)
 -              strbuf_setlen(msg, msg->len - 1);
  }
  
  static void run_diff_cmd(const char *pgm,
  {
        const char *xfrm_msg = NULL;
        int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
+       int must_show_header = 0;
  
 -      if (msg) {
 -              fill_metainfo(msg, name, other, one, two, o, p, &must_show_header);
 -              xfrm_msg = msg->len ? msg->buf : NULL;
 -      }
 -
        if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
                pgm = NULL;
        else {
                        pgm = drv->external;
        }
  
 +      if (msg) {
 +              /*
 +               * don't use colors when the header is intended for an
 +               * external diff driver
 +               */
 +              fill_metainfo(msg, name, other, one, two, o, p,
++                            &must_show_header,
 +                            DIFF_OPT_TST(o, COLOR_DIFF) && !pgm);
 +              xfrm_msg = msg->len ? msg->buf : NULL;
 +      }
 +
        if (pgm) {
                run_external_diff(pgm, name, other, one, two, xfrm_msg,
                                  complete_rewrite);
        }
        if (one && two)
                builtin_diff(name, other ? other : name,
-                            one, two, xfrm_msg, o, complete_rewrite);
+                            one, two, xfrm_msg, must_show_header,
+                            o, complete_rewrite);
        else
                fprintf(o->file, "* Unmerged path %s\n", name);
  }
@@@ -2638,12 -2636,6 +2649,12 @@@ int diff_setup_done(struct diff_option
         */
        if (options->pickaxe)
                DIFF_OPT_SET(options, RECURSIVE);
 +      /*
 +       * When patches are generated, submodules diffed against the work tree
 +       * must be checked for dirtiness too so it can be shown in the output
 +       */
 +      if (options->output_format & DIFF_FORMAT_PATCH)
 +              DIFF_OPT_SET(options, DIRTY_SUBMODULES);
  
        if (options->detect_rename && options->rename_limit < 0)
                options->rename_limit = diff_rename_limit_default;
@@@ -2842,15 -2834,6 +2853,15 @@@ int diff_opt_parse(struct diff_options 
                DIFF_OPT_SET(options, FOLLOW_RENAMES);
        else if (!strcmp(arg, "--color"))
                DIFF_OPT_SET(options, COLOR_DIFF);
 +      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
 +                      return error("option `color' expects \"always\", \"auto\", or \"never\"");
 +      }
        else if (!strcmp(arg, "--no-color"))
                DIFF_OPT_CLR(options, COLOR_DIFF);
        else if (!strcmp(arg, "--color-words")) {
@@@ -3102,8 -3085,7 +3113,8 @@@ int diff_unmodified_pair(struct diff_fi
         * dealing with a change.
         */
        if (one->sha1_valid && two->sha1_valid &&
 -          !hashcmp(one->sha1, two->sha1))
 +          !hashcmp(one->sha1, two->sha1) &&
 +          !one->dirty_submodule && !two->dirty_submodule)
                return 1; /* no change */
        if (!one->sha1_valid && !two->sha1_valid)
                return 1; /* both look at the same file on the filesystem. */
@@@ -3238,8 -3220,6 +3249,8 @@@ static void diff_resolve_rename_copy(vo
                }
                else if (hashcmp(p->one->sha1, p->two->sha1) ||
                         p->one->mode != p->two->mode ||
 +                       p->one->dirty_submodule ||
 +                       p->two->dirty_submodule ||
                         is_null_sha1(p->one->sha1))
                        p->status = DIFF_STATUS_MODIFIED;
                else {
@@@ -3445,7 -3425,7 +3456,7 @@@ static int diff_get_patch_id(struct dif
                                        len2, p->two->path);
                git_SHA1_Update(&ctx, buffer, len1);
  
 -              xpp.flags = XDF_NEED_MINIMAL;
 +              xpp.flags = 0;
                xecfg.ctxlen = 3;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,