Merge branch 'lt/diffgen' into next

* lt/diffgen:
  built-in diff: minimum tweaks
  builtin-diff: \No newline at end of file.
  Use a *real* built-in diff generator
This commit is contained in:
Junio C Hamano
2006-03-25 17:44:01 -08:00
15 changed files with 1864 additions and 9 deletions

110
diff.c
View File

@ -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,70 @@ 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;
}
struct emit_callback {
const char **label_path;
};
static int fn_out(void *priv, mmbuffer_t *mb, int nbuf)
{
int i;
struct emit_callback *ecbdata = priv;
if (ecbdata->label_path[0]) {
printf("--- %s\n", ecbdata->label_path[0]);
printf("+++ %s\n", ecbdata->label_path[1]);
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
}
for (i = 0; i < nbuf; i++)
if (!fwrite(mb[i].ptr, mb[i].size, 1, stdout))
return -1;
return 0;
}
#define FIRST_FEW_BYTES 8000
static int mmfile_is_binary(mmfile_t *mf)
{
long sz = mf->size;
if (FIRST_FEW_BYTES < sz)
sz = FIRST_FEW_BYTES;
if (memchr(mf->ptr, 0, sz))
return 1;
return 0;
}
static const char *builtin_diff(const char *name_a,
const char *name_b,
struct diff_tempfile *temp,
@ -186,6 +251,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 +321,44 @@ 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);
if (fill_mmfile(&mf1, temp[0].name) < 0 ||
fill_mmfile(&mf2, temp[1].name) < 0)
die("unable to read files to diff");
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
printf("Binary files %s and %s differ\n",
label_path[0], label_path[1]);
else {
/* Crazy xdl interfaces.. */
const char *diffopts = getenv("GIT_DIFF_OPTS");
xpparam_t xpp;
xdemitconf_t xecfg;
xdemitcb_t ecb;
struct emit_callback ecbdata;
ecbdata.label_path = label_path;
xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = 3;
if (!diffopts)
;
else if (!strncmp(diffopts, "--unified=", 10))
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
else if (!strncmp(diffopts, "-u", 2))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = fn_out;
ecb.priv = &ecbdata;
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
}
free(mf1.ptr);
free(mf2.ptr);
return NULL;
}
struct diff_filespec *alloc_filespec(const char *path)