built-in diff: minimum tweaks
authorJunio C Hamano <junkio@cox.net>
Sat, 25 Mar 2006 20:16:17 +0000 (12:16 -0800)
committerJunio C Hamano <junkio@cox.net>
Sun, 26 Mar 2006 00:50:00 +0000 (16:50 -0800)
This fixes up a couple of minor issues with the real built-in
diff to be more usable:

 - Omit ---/+++ header unless we emit diff output;

 - Detect and punt binary diff like GNU does;

 - Honor GIT_DIFF_OPTS minimally (only -u<number> and
   --unified=<number> are currently supported);

 - Omit line count of 1 from "@@ -l,k +m,n @@" hunk header
   (i.e. when k == 1 or n == 1)

 - Adjust testsuite for the lack of -p support.

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff.c
t/t4001-diff-rename.sh
xdiff/xutils.c

diff --git a/diff.c b/diff.c
index f6a1f5ded4034e67d582b712f5061299040a2eb3..cd2ce0fdf58220ed718dd815be95c1aee93cb044 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -212,16 +212,37 @@ static int fill_mmfile(mmfile_t *mf, const char *file)
        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,
@@ -306,22 +327,32 @@ static const char *builtin_diff(const char *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.. */
-       {
+       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);
        }
 
index 2e3c20d6b9468bf413e97d422e7dbe13ac4238cd..08c11319a70be6dfbcc530d9462c36254a3acd8e 100755 (executable)
@@ -49,7 +49,7 @@ rename from path0
 rename to path1
 --- a/path0
 +++ b/path1
-@@ -8,7 +8,7 @@ Line 7
+@@ -8,7 +8,7 @@
  Line 8
  Line 9
  Line 10
index b68afa25c1d6e285005b2b84472b2faf62883a9d..8221806f78bab437e8863c3fb2ea6229ddae9bca 100644 (file)
@@ -245,20 +245,24 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
 
        nb += xdl_num_out(buf + nb, c1 ? s1: 0);
 
-       memcpy(buf + nb, ",", 1);
-       nb += 1;
+       if (c1 != 1) {
+               memcpy(buf + nb, ",", 1);
+               nb += 1;
 
-       nb += xdl_num_out(buf + nb, c1);
+               nb += xdl_num_out(buf + nb, c1);
+       }
 
        memcpy(buf + nb, " +", 2);
        nb += 2;
 
        nb += xdl_num_out(buf + nb, c2 ? s2: 0);
 
-       memcpy(buf + nb, ",", 1);
-       nb += 1;
+       if (c2 != 1) {
+               memcpy(buf + nb, ",", 1);
+               nb += 1;
 
-       nb += xdl_num_out(buf + nb, c2);
+               nb += xdl_num_out(buf + nb, c2);
+       }
 
        memcpy(buf + nb, " @@\n", 4);
        nb += 4;