Merge branch 'jk/diff-convfilter'
authorJunio C Hamano <gitster@pobox.com>
Thu, 13 Nov 2008 05:50:58 +0000 (21:50 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 13 Nov 2008 05:50:58 +0000 (21:50 -0800)
* jk/diff-convfilter:
enable textconv for diff in verbose status/commit
wt-status: load diff ui config
only textconv regular files
userdiff: require explicitly allowing textconv
refactor userdiff textconv code

Conflicts:
t/t4030-diff-textconv.sh

1  2 
builtin-diff.c
diff.c
t/t4030-diff-textconv.sh
diff --combined builtin-diff.c
index 82d4ddabd85072829199fe8dc17c2de15691dac2,2de5834c119242d2fd5d2e6766f7ed372fd89524..7ceceeb6ff49d60468293941b5f37141e8fc01b9
@@@ -118,7 -118,7 +118,7 @@@ static int builtin_diff_index(struct re
        int cached = 0;
        while (1 < argc) {
                const char *arg = argv[1];
 -              if (!strcmp(arg, "--cached"))
 +              if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged"))
                        cached = 1;
                else
                        usage(builtin_diff_usage);
@@@ -300,6 -300,7 +300,7 @@@ int cmd_diff(int argc, const char **arg
        }
        DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
        DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
+       DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
  
        /*
         * If the user asked for our exit code then don't start a
                        const char *arg = argv[i];
                        if (!strcmp(arg, "--"))
                                break;
 -                      else if (!strcmp(arg, "--cached")) {
 +                      else if (!strcmp(arg, "--cached") ||
 +                               !strcmp(arg, "--staged")) {
                                add_head_to_pending(&rev);
                                if (!rev.pending.nr)
                                        die("No HEAD commit to compare with (yet)");
diff --combined diff.c
index 3e6c752bb77109864f8be170f9b0e2504531b2aa,23d454e71d4d22165d995d8fd321c86d2eeb84e4..f644947c823e824a294414a660beac02b4182fe4
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -93,12 -93,6 +93,6 @@@ int git_diff_ui_config(const char *var
        if (!strcmp(var, "diff.external"))
                return git_config_string(&external_diff_cmd_cfg, var, value);
  
-       switch (userdiff_config_porcelain(var, value)) {
-               case 0: break;
-               case -1: return -1;
-               default: return 0;
-       }
        return git_diff_basic_config(var, value, cb);
  }
  
@@@ -109,6 -103,12 +103,12 @@@ int git_diff_basic_config(const char *v
                return 0;
        }
  
+       switch (userdiff_config(var, value)) {
+               case 0: break;
+               case -1: return -1;
+               default: return 0;
+       }
        if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
                if (!value)
                return 0;
        }
  
-       switch (userdiff_config_basic(var, value)) {
-               case 0: break;
-               case -1: return -1;
-               default: return 0;
-       }
        return git_color_default_config(var, value, cb);
  }
  
@@@ -294,18 -288,8 +288,8 @@@ static int fill_mmfile(mmfile_t *mf, st
        else if (diff_populate_filespec(one, 0))
                return -1;
  
-       diff_filespec_load_driver(one);
-       if (one->driver->textconv) {
-               size_t size;
-               mf->ptr = run_textconv(one->driver->textconv, one, &size);
-               if (!mf->ptr)
-                       return -1;
-               mf->size = size;
-       }
-       else {
-               mf->ptr = one->data;
-               mf->size = one->size;
-       }
+       mf->ptr = one->data;
+       mf->size = one->size;
        return 0;
  }
  
@@@ -400,7 -384,6 +384,7 @@@ static void diff_words_show(struct diff
        mmfile_t minus, plus;
        int i;
  
 +      memset(&xpp, 0, sizeof(xpp));
        memset(&xecfg, 0, sizeof(xecfg));
        minus.size = diff_words->minus.text.size;
        minus.ptr = xmalloc(minus.size);
@@@ -1324,6 -1307,16 +1308,16 @@@ void diff_set_mnemonic_prefix(struct di
                options->b_prefix = b;
  }
  
+ static const char *get_textconv(struct diff_filespec *one)
+ {
+       if (!DIFF_FILE_VALID(one))
+               return NULL;
+       if (!S_ISREG(one->mode))
+               return NULL;
+       diff_filespec_load_driver(one);
+       return one->driver->textconv;
+ }
  static void builtin_diff(const char *name_a,
                         const char *name_b,
                         struct diff_filespec *one,
        const char *set = diff_get_color_opt(o, DIFF_METAINFO);
        const char *reset = diff_get_color_opt(o, DIFF_RESET);
        const char *a_prefix, *b_prefix;
+       const char *textconv_one = NULL, *textconv_two = NULL;
  
        diff_set_mnemonic_prefix(o, "a/", "b/");
        if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
  
+       if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
+               textconv_one = get_textconv(one);
+               textconv_two = get_textconv(two);
+       }
        if (!DIFF_OPT_TST(o, TEXT) &&
-           (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) {
+           ( (diff_filespec_is_binary(one) && !textconv_one) ||
+             (diff_filespec_is_binary(two) && !textconv_two) )) {
                /* Quite common confusing case */
                if (mf1.size == mf2.size &&
                    !memcmp(mf1.ptr, mf2.ptr, mf1.size))
                struct emit_callback ecbdata;
                const struct userdiff_funcname *pe;
  
+               if (textconv_one) {
+                       size_t size;
+                       mf1.ptr = run_textconv(textconv_one, one, &size);
+                       if (!mf1.ptr)
+                               die("unable to read files to diff");
+                       mf1.size = size;
+               }
+               if (textconv_two) {
+                       size_t size;
+                       mf2.ptr = run_textconv(textconv_two, two, &size);
+                       if (!mf2.ptr)
+                               die("unable to read files to diff");
+                       mf2.size = size;
+               }
                pe = diff_funcname_pattern(one);
                if (!pe)
                        pe = diff_funcname_pattern(two);
  
 +              memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                memset(&ecbdata, 0, sizeof(ecbdata));
                ecbdata.label_path = lbl;
                              &xpp, &xecfg, &ecb);
                if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
                        free_diff_words_data(&ecbdata);
+               if (textconv_one)
+                       free(mf1.ptr);
+               if (textconv_two)
+                       free(mf2.ptr);
        }
  
   free_ab_and_return:
@@@ -1491,7 -1509,6 +1511,7 @@@ static void builtin_diffstat(const cha
                xdemitconf_t xecfg;
                xdemitcb_t ecb;
  
 +              memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
@@@ -1538,7 -1555,6 +1558,7 @@@ static void builtin_checkdiff(const cha
                xdemitconf_t xecfg;
                xdemitcb_t ecb;
  
 +              memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
                xpp.flags = XDF_NEED_MINIMAL;
@@@ -2962,7 -2978,6 +2982,7 @@@ static int diff_get_patch_id(struct dif
                struct diff_filepair *p = q->queue[i];
                int len1, len2;
  
 +              memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                if (p->status == 0)
                        return error("internal diff status error");
diff --combined t/t4030-diff-textconv.sh
index 3aed1bbdfed0f415a615f77c72210336d83f33ed,09967f56639035d12c5211d56e82ef2ef51e512d..03ba26a0de7d1bf41269cfb1f1b9f33b733482e1
@@@ -52,7 -52,7 +52,7 @@@ test_expect_success 'setup textconv fil
        git config diff.fail.textconv false
  '
  
- test_expect_failure 'diff produces text' '
+ test_expect_success 'diff produces text' '
        git diff HEAD^ HEAD >diff &&
        find_diff <diff >actual &&
        test_cmp expect.text actual
@@@ -64,23 -64,31 +64,31 @@@ test_expect_success 'diff-tree produce
        test_cmp expect.binary actual
  '
  
- test_expect_failure 'log produces text' '
+ test_expect_success 'log produces text' '
        git log -1 -p >log &&
        find_diff <log >actual &&
        test_cmp expect.text actual
  '
  
- test_expect_failure 'format-patch produces binary' '
+ test_expect_success 'format-patch produces binary' '
        git format-patch --no-binary --stdout HEAD^ >patch &&
        find_diff <patch >actual &&
        test_cmp expect.binary actual
  '
  
+ test_expect_success 'status -v produces text' '
+       git reset --soft HEAD^ &&
+       git status -v >diff &&
+       find_diff <diff >actual &&
+       test_cmp expect.text actual &&
+       git reset --soft HEAD@{1}
+ '
  cat >expect.stat <<'EOF'
   file |  Bin 2 -> 4 bytes
   1 files changed, 0 insertions(+), 0 deletions(-)
  EOF
- test_expect_failure 'diffstat does not run textconv' '
+ test_expect_success 'diffstat does not run textconv' '
        echo file diff=fail >.gitattributes &&
        git diff --stat HEAD^ HEAD >actual &&
        test_cmp expect.stat actual
@@@ -104,8 -112,8 +112,8 @@@ index ad8b3d2..67be42
  \ No newline at end of file
  EOF
  # make a symlink the hard way that works on symlink-challenged file systems
- test_expect_failure 'textconv does not act on symlinks' '
+ test_expect_success 'textconv does not act on symlinks' '
 -      echo -n frotz > file &&
 +      printf frotz > file &&
        git add file &&
        git ls-files -s | sed -e s/100644/120000/ |
                git update-index --index-info &&