Merge branch 'lt/diffgen' into next
authorJunio C Hamano <junkio@cox.net>
Sun, 26 Mar 2006 01:44:01 +0000 (17:44 -0800)
committerJunio C Hamano <junkio@cox.net>
Sun, 26 Mar 2006 01:44:01 +0000 (17:44 -0800)
* lt/diffgen:
  built-in diff: minimum tweaks
  builtin-diff: \No newline at end of file.
  Use a *real* built-in diff generator

1  2 
Makefile
diff.c

diff --combined Makefile
+++ b/Makefile
@@@ -188,9 -188,10 +188,10 @@@ PYMODULES = 
        gitMergeCommon.py
  
  LIB_FILE=libgit.a
+ XDIFF_LIB=xdiff/lib.a
  
  LIB_H = \
 -      blob.h cache.h commit.h count-delta.h csum-file.h delta.h \
 +      blob.h cache.h commit.h csum-file.h delta.h \
        diff.h object.h pack.h pkt-line.h quote.h refs.h \
        run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h
  
@@@ -200,7 -201,7 +201,7 @@@ DIFF_OBJS = 
        diffcore-delta.o
  
  LIB_OBJS = \
 -      blob.o commit.o connect.o count-delta.o csum-file.o \
 +      blob.o commit.o connect.o csum-file.o \
        date.o diff-delta.o entry.o exec_cmd.o ident.o index.o \
        object.o pack-check.o patch-delta.o path.o pkt-line.o \
        quote.o read-cache.o refs.o run-command.o \
        fetch-clone.o revision.o pager.o \
        $(DIFF_OBJS)
  
- LIBS = $(LIB_FILE)
+ LIBS = $(LIB_FILE) $(XDIFF_LIB)
  LIBS += -lz
  
  #
@@@ -544,12 -545,18 +545,18 @@@ init-db.o: init-db.
                -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
  
  $(LIB_OBJS): $(LIB_H)
- $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H)
+ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIBS)
  $(DIFF_OBJS): diffcore.h
  
  $(LIB_FILE): $(LIB_OBJS)
        $(AR) rcs $@ $(LIB_OBJS)
  
+ XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o
+ $(XDIFF_LIB): $(XDIFF_OBJS)
+       $(AR) rcs $@ $(XDIFF_OBJS)
  doc:
        $(MAKE) -C Documentation all
  
diff --combined diff.c
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -8,6 -8,7 +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 +179,70 @@@ static void emit_rewrite_diff(const cha
                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,
                         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];
                }
        }
  
-       /* 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)
@@@ -463,8 -561,6 +561,8 @@@ void diff_free_filespec_data(struct dif
                munmap(s->data, s->size);
        s->should_free = s->should_munmap = 0;
        s->data = NULL;
 +      free(s->cnt_data);
 +      s->cnt_data = NULL;
  }
  
  static void prep_temp_blob(struct diff_tempfile *temp,