diff options
Diffstat (limited to 'diff.c')
-rw-r--r-- | diff.c | 79 |
1 files changed, 73 insertions, 6 deletions
@@ -8,6 +8,7 @@ #include "quote.h" #include "diff.h" #include "diffcore.h" +#include "xdiff/xdiff.h" static const char *diff_opts = "-pu"; @@ -178,6 +179,49 @@ static void emit_rewrite_diff(const char *name_a, copy_file('+', temp[1].name); } +static int fill_mmfile(mmfile_t *mf, const char *file) +{ + int fd = open(file, O_RDONLY); + struct stat st; + char *buf; + unsigned long size; + + mf->ptr = NULL; + mf->size = 0; + if (fd < 0) + return 0; + fstat(fd, &st); + size = st.st_size; + buf = xmalloc(size); + mf->ptr = buf; + mf->size = size; + while (size) { + int retval = read(fd, buf, size); + if (retval < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + break; + } + if (!retval) + break; + buf += retval; + size -= retval; + } + mf->size -= size; + close(fd); + return 0; +} + +static int fn_out(void *priv, mmbuffer_t *mb, int nbuf) +{ + int i; + + for (i = 0; i < nbuf; i++) + if (!fwrite(mb[i].ptr, mb[i].size, 1, stdout)) + return -1; + return 0; +} + static const char *builtin_diff(const char *name_a, const char *name_b, struct diff_tempfile *temp, @@ -186,6 +230,7 @@ static const char *builtin_diff(const char *name_a, const char **args) { int i, next_at, cmd_size; + mmfile_t mf1, mf2; const char *const diff_cmd = "diff -L%s -L%s"; const char *const diff_arg = "-- %s %s||:"; /* "||:" is to return 0 */ const char *input_name_sq[2]; @@ -255,12 +300,34 @@ static const char *builtin_diff(const char *name_a, } } - /* This is disgusting */ - *args++ = "sh"; - *args++ = "-c"; - *args++ = cmd; - *args = NULL; - return "/bin/sh"; + /* Un-quote the paths */ + if (label_path[0][0] != '/') + label_path[0] = quote_two("a/", name_a); + if (label_path[1][0] != '/') + label_path[1] = quote_two("b/", name_b); + + printf("--- %s\n", label_path[0]); + printf("+++ %s\n", label_path[1]); + + if (fill_mmfile(&mf1, temp[0].name) < 0 || + fill_mmfile(&mf2, temp[1].name) < 0) + die("unable to read files to diff"); + + /* Crazy xdl interfaces.. */ + { + xpparam_t xpp; + xdemitconf_t xecfg; + xdemitcb_t ecb; + + xpp.flags = XDF_NEED_MINIMAL; + xecfg.ctxlen = 3; + ecb.outf = fn_out; + xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + } + + free(mf1.ptr); + free(mf2.ptr); + return NULL; } struct diff_filespec *alloc_filespec(const char *path) |