summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--diff.c49
-rw-r--r--userdiff.c2
-rw-r--r--userdiff.h1
3 files changed, 50 insertions, 2 deletions
diff --git a/diff.c b/diff.c
index dabd7f50ec..e368fef14f 100644
--- 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;
}
@@ -3373,3 +3387,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);
+}
diff --git a/userdiff.c b/userdiff.c
index 58478a6912..d95257ab3b 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -140,6 +140,8 @@ int userdiff_config_porcelain(const char *k, const char *v)
if ((drv = parse_driver(k, v, "command")))
return parse_string(&drv->external, k, v);
+ if ((drv = parse_driver(k, v, "textconv")))
+ return parse_string(&drv->textconv, k, v);
return 0;
}
diff --git a/userdiff.h b/userdiff.h
index 1c1eb042b4..f29c18ffb3 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -11,6 +11,7 @@ struct userdiff_driver {
const char *external;
int binary;
struct userdiff_funcname funcname;
+ const char *textconv;
};
int userdiff_config_basic(const char *k, const char *v);