xdiff: Show function names in hunk headers.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 28 Mar 2006 02:23:31 +0000 (03:23 +0100)
committerJunio C Hamano <junkio@cox.net>
Tue, 28 Mar 2006 02:43:51 +0000 (18:43 -0800)
The speed of the built-in diff generator is nice; but the function names
shown by `diff -p' are /really/ nice.  And I hate having to choose.  So,
we hack xdiff to find the function names and print them.

xdiff has grown a flag to say whether to dig up the function names.  The
builtin_diff function passes this flag unconditionally.  I suppose it
could parse GIT_DIFF_OPTS, but it doesn't at the moment.  I've also
reintroduced the `function name' into the test suite, from which it was
removed in commit 3ce8f089.

The function names are parsed by a particularly stupid algorithm at the
moment: it just tries to find a line in the `old' file, from before the
start of the hunk, whose first character looks plausible.  Still, it's
most definitely a start.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
Signed-off-by: Junio C Hamano <junkio@cox.net>
diff.c
t/t4001-diff-rename.sh
xdiff/xdiff.h
xdiff/xemit.c
xdiff/xinclude.h
xdiff/xutils.c
xdiff/xutils.h

diff --git a/diff.c b/diff.c
index 5eae094..8b37477 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -267,6 +267,7 @@ static void builtin_diff(const char *name_a,
                ecbdata.label_path = lbl;
                xpp.flags = XDF_NEED_MINIMAL;
                xecfg.ctxlen = 3;
+               xecfg.flags = XDL_EMIT_FUNCNAMES;
                if (!diffopts)
                        ;
                else if (!strncmp(diffopts, "--unified=", 10))
index 08c1131..2e3c20d 100755 (executable)
@@ -49,7 +49,7 @@ rename from path0
 rename to path1
 --- a/path0
 +++ b/path1
-@@ -8,7 +8,7 @@
+@@ -8,7 +8,7 @@ Line 7
  Line 8
  Line 9
  Line 10
index 71cb939..2540e8a 100644 (file)
@@ -35,6 +35,8 @@ extern "C" {
 #define XDL_PATCH_MODEMASK ((1 << 8) - 1)
 #define XDL_PATCH_IGNOREBSPACE (1 << 8)
 
+#define XDL_EMIT_FUNCNAMES (1 << 0)
+
 #define XDL_MMB_READONLY (1 << 0)
 
 #define XDL_MMF_ATOMIC (1 << 0)
@@ -65,6 +67,7 @@ typedef struct s_xdemitcb {
 
 typedef struct s_xdemitconf {
        long ctxlen;
+       unsigned long flags;
 } xdemitconf_t;
 
 typedef struct s_bdiffparam {
index 2e5d54c..ad5bfb1 100644 (file)
@@ -69,10 +69,43 @@ static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
 }
 
 
+static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) {
+
+       /*
+        * Be quite stupid about this for now.  Find a line in the old file
+        * before the start of the hunk (and context) which starts with a
+        * plausible character.
+        */
+
+       const char *rec;
+       long len;
+
+       *ll = 0;
+       while (i-- > 0) {
+               len = xdl_get_rec(xf, i, &rec);
+               if (len > 0 &&
+                   (isalpha((unsigned char)*rec) || /* identifier? */
+                    *rec == '_' ||     /* also identifier? */
+                    *rec == '(' ||     /* lisp defun? */
+                    *rec == '#')) {    /* #define? */
+                       if (len > sz)
+                               len = sz;
+                       if (len && rec[len - 1] == '\n')
+                               len--;
+                       memcpy(buf, rec, len);
+                       *ll = len;
+                       return;
+               }
+       }
+}
+
+
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                  xdemitconf_t const *xecfg) {
        long s1, s2, e1, e2, lctx;
        xdchange_t *xch, *xche;
+       char funcbuf[40];
+       long funclen = 0;
 
        for (xch = xche = xscr; xch; xch = xche->next) {
                xche = xdl_get_hunk(xch, xecfg);
@@ -90,7 +123,13 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                /*
                 * Emit current hunk header.
                 */
-               if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ecb) < 0)
+
+               if (xecfg->flags & XDL_EMIT_FUNCNAMES) {
+                       xdl_find_func(&xe->xdf1, s1, funcbuf,
+                                     sizeof(funcbuf), &funclen);
+               }
+               if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
+                                     funcbuf, funclen, ecb) < 0)
                        return -1;
 
                /*
index 9490fc5..04a9da8 100644 (file)
@@ -23,6 +23,7 @@
 #if !defined(XINCLUDE_H)
 #define XINCLUDE_H
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
index 8221806..afaada1 100644 (file)
@@ -235,7 +235,8 @@ long xdl_atol(char const *str, char const **next) {
 }
 
 
-int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
+int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
+                     const char *func, long funclen, xdemitcb_t *ecb) {
        int nb = 0;
        mmbuffer_t mb;
        char buf[128];
@@ -264,8 +265,16 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
                nb += xdl_num_out(buf + nb, c2);
        }
 
-       memcpy(buf + nb, " @@\n", 4);
-       nb += 4;
+       memcpy(buf + nb, " @@", 3);
+       nb += 3;
+       if (func && funclen) {
+               buf[nb++] = ' ';
+               if (funclen > sizeof(buf) - nb - 1)
+                       funclen = sizeof(buf) - nb - 1;
+               memcpy(buf + nb, func, funclen);
+               nb += funclen;
+       }
+       buf[nb++] = '\n';
 
        mb.ptr = buf;
        mb.size = nb;
index 428a4bb..55b0d39 100644 (file)
@@ -36,7 +36,8 @@ unsigned long xdl_hash_record(char const **data, char const *top);
 unsigned int xdl_hashbits(unsigned int size);
 int xdl_num_out(char *out, long val);
 long xdl_atol(char const *str, char const **next);
-int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb);
+int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
+                     const char *func, long funclen, xdemitcb_t *ecb);