]> asedeno.scripts.mit.edu Git - git.git/blobdiff - diff.c
Merge git://repo.or.cz/git-gui
[git.git] / diff.c
diff --git a/diff.c b/diff.c
index dabd7f50ec28ed804cf5cace06cf72753be562ae..1918b73d5368d1ad89f501e63777e47763d0d0fe 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -38,6 +38,9 @@ static char diff_colors[][COLOR_MAXLEN] = {
        "\033[41m",     /* WHITESPACE (red background) */
 };
 
+static void diff_filespec_load_driver(struct diff_filespec *one);
+static char *run_textconv(const char *, struct diff_filespec *, size_t *);
+
 static int parse_diff_color_slot(const char *var, int ofs)
 {
        if (!strcasecmp(var+ofs, "plain"))
@@ -290,8 +293,19 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
        }
        else if (diff_populate_filespec(one, 0))
                return -1;
-       mf->ptr = one->data;
-       mf->size = one->size;
+
+       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;
+       }
        return 0;
 }
 
@@ -386,6 +400,7 @@ static void diff_words_show(struct diff_words_data *diff_words)
        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);
@@ -1402,6 +1417,7 @@ static void builtin_diff(const char *name_a,
                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;
@@ -1475,6 +1491,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                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,
@@ -1521,6 +1538,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                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;
@@ -2944,6 +2962,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                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");
@@ -3373,3 +3392,34 @@ void diff_unmerge(struct diff_options *options,
        fill_filespec(one, sha1, mode);
        diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
 }
+
+static char *run_textconv(const char *pgm, struct diff_filespec *spec,
+               size_t *outsize)
+{
+       struct diff_tempfile temp;
+       const char *argv[3];
+       const char **arg = argv;
+       struct child_process child;
+       struct strbuf buf = STRBUF_INIT;
+
+       prepare_temp_file(spec->path, &temp, spec);
+       *arg++ = pgm;
+       *arg++ = temp.name;
+       *arg = NULL;
+
+       memset(&child, 0, sizeof(child));
+       child.argv = argv;
+       child.out = -1;
+       if (start_command(&child) != 0 ||
+           strbuf_read(&buf, child.out, 0) < 0 ||
+           finish_command(&child) != 0) {
+               if (temp.name == temp.tmp_path)
+                       unlink(temp.name);
+               error("error running textconv command '%s'", pgm);
+               return NULL;
+       }
+       if (temp.name == temp.tmp_path)
+               unlink(temp.name);
+
+       return strbuf_detach(&buf, outsize);
+}