From: "Bhushan G. Lodha & David A. Dalrymple" <dad-...@mit.edu>

For filtering by function names, it's useful to split hunks whenever a
function line is encountered, so that each function name being deleted
or inserted gets its own hunk header (which then can be easily detected
by the filter).

This adds a flag, XDL_EMIT_MOREHUNKHEADS, which triggers this
nonstandard behavior, and enables it only in case the --function-name
option is being used.

Signed-off-by: David Dalrymple (on zayin) <davi...@alum.mit.edu>
---
 diff.c             |  3 ++-
 diffcore-pickaxe.c |  3 ++-
 xdiff/xdiff.h      |  1 +
 xdiff/xdiffi.c     |  2 +-
 xdiff/xemit.c      | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 xdiff/xemit.h      |  4 +++-
 6 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/diff.c b/diff.c
index 914b4a2..a86206c 100644
--- a/diff.c
+++ b/diff.c
@@ -2381,7 +2381,8 @@ static void builtin_diff(const char *name_a,
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
                if (o->funcname)
-                       xecfg.flags |= XDL_EMIT_MOREFUNCNAMES;
+                       xecfg.flags |= XDL_EMIT_MOREFUNCNAMES
+                                   | XDL_EMIT_MOREHUNKHEADS;
                if (DIFF_OPT_TST(o, FUNCCONTEXT))
                        xecfg.flags |= XDL_EMIT_FUNCCONTEXT;
                if (pe)
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index ab31c18..d9f4c30 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -164,7 +164,8 @@ static int diff_funcname_filter(mmfile_t *one, mmfile_t 
*two,
        xecfg.interhunkctxlen = o->interhunkcontext;
        if (!(one && two))
                xecfg.flags = XDL_EMIT_FUNCCONTEXT;
-       xecfg.flags |= XDL_EMIT_FUNCNAMES | XDL_EMIT_MOREFUNCNAMES;
+       xecfg.flags |= XDL_EMIT_FUNCNAMES | XDL_EMIT_MOREFUNCNAMES
+                   | XDL_EMIT_MOREHUNKHEADS;
        xdi_diff_outf(one, two, match_funcname, &ecbdata, &xpp, &xecfg);
        return ecbdata.hit;
 }
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 469bded..787c376 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -45,6 +45,7 @@
 #define XDL_EMIT_COMMON (1 << 1)
 #define XDL_EMIT_FUNCCONTEXT (1 << 2)
 #define XDL_EMIT_MOREFUNCNAMES (1 << 3)
+#define XDL_EMIT_MOREHUNKHEADS (1 << 4)
 
 #define XDL_MMB_READONLY (1 << 0)
 
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 2358a2d..c29804e 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -545,7 +545,7 @@ static int xdl_call_hunk_func(xdfenv_t *xe, xdchange_t 
*xscr, xdemitcb_t *ecb,
        xdchange_t *xch, *xche;
 
        for (xch = xscr; xch; xch = xche->next) {
-               xche = xdl_get_hunk(&xch, xecfg);
+               xche = xdl_get_hunk(xe, &xch, xecfg);
                if (!xch)
                        break;
                if (xecfg->hunk_func(xch->i1, xche->i1 + xche->chg1 - xch->i1,
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index 0ddb094..f49eaaf 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -29,6 +29,9 @@ struct func_line {
 };
 
 
+static long get_func_line(xdfile_t *xdf, xdemitconf_t const *xecfg,
+                         struct func_line *func_line, long start, long limit);
+
 static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
 static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t 
*ecb);
 
@@ -62,7 +65,7 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const 
*pre, xdemitcb_t *
  * inside the differential hunk according to the specified configuration.
  * Also advance xscr if the first changes must be discarded.
  */
-xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
+xdchange_t *xdl_get_hunk(xdfenv_t *xe, xdchange_t **xscr, xdemitconf_t const 
*xecfg)
 {
        xdchange_t *xch, *xchp, *lxch;
        long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
@@ -83,6 +86,59 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t 
const *xecfg)
 
        lxch = *xscr;
 
+       if (xecfg->flags & XDL_EMIT_MOREHUNKHEADS)
+               for (xch = *xscr; xch; xch=xch->next) {
+                       /*
+                        * If a current change contains a func_line, end this
+                        * hunk immediately before and create a new hunk
+                        * starting from that line.
+                        */
+                       long fl_in_xch1 = get_func_line(&xe->xdf1, xecfg, NULL,
+                                               xch->i1, xch->i1+xch->chg1);
+                       long fl_in_xch2 = get_func_line(&xe->xdf2, xecfg, NULL,
+                                               xch->i2, xch->i2+xch->chg2);
+                       if (fl_in_xch1 >= xch->i1 && fl_in_xch2 >= xch->i2) {
+                               xdchange_t *new_next =
+                                       (xdchange_t 
*)xdl_malloc(sizeof(xdchange_t));
+                               new_next->i1 = xch->i1+xch->chg1;
+                               new_next->chg1 = 0;
+                               new_next->i2 = xch->i2;
+                               new_next->chg2 = xch->chg2;
+                               new_next->ignore = xch->ignore;
+                               new_next->next = xch->next;
+                               xch->next = new_next;
+                               xch->chg2 = 0;
+                               return xch;
+                       }
+                       if (fl_in_xch1 > xch->i1) {
+                               xdchange_t *new_next =
+                                       (xdchange_t 
*)xdl_malloc(sizeof(xdchange_t));
+                               new_next->i1 = fl_in_xch1;
+                               new_next->chg1 = (xch->i1+xch->chg1)-fl_in_xch1;
+                               new_next->i2 = xch->i2;
+                               new_next->chg2 = xch->chg2;
+                               new_next->ignore = xch->ignore;
+                               new_next->next = xch->next;
+                               xch->next = new_next;
+                               xch->chg1 = fl_in_xch1 - xch->i1;
+                               xch->chg2 = 0;
+                               return xch;
+                       }
+                       if (fl_in_xch2 > xch->i2) {
+                               xdchange_t *new_next =
+                                       (xdchange_t 
*)xdl_malloc(sizeof(xdchange_t));
+                               new_next->i2 = fl_in_xch2;
+                               new_next->chg2 = (xch->i2+xch->chg2)-fl_in_xch2;
+                               new_next->i1 = xch->i1+xch->chg1;
+                               new_next->chg1 = 0;
+                               new_next->ignore = xch->ignore;
+                               new_next->next = xch->next;
+                               xch->next = new_next;
+                               xch->chg2 = fl_in_xch2 - xch->i2;
+                               return xch;
+                       }
+               }
+
        for (xchp = *xscr, xch = xchp->next; xch; xchp = xch, xch = xch->next) {
                long distance = xch->i1 - (xchp->i1 + xchp->chg1);
                if (distance > max_common)
@@ -173,7 +229,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, 
xdemitcb_t *ecb,
                return xdl_emit_common(xe, xscr, ecb, xecfg);
 
        for (xch = xscr; xch; xch = xche->next) {
-               xche = xdl_get_hunk(&xch, xecfg);
+               xche = xdl_get_hunk(xe, &xch, xecfg);
                if (!xch)
                        break;
 
diff --git a/xdiff/xemit.h b/xdiff/xemit.h
index d297107..4d584f5 100644
--- a/xdiff/xemit.h
+++ b/xdiff/xemit.h
@@ -27,7 +27,9 @@
 typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                           xdemitconf_t const *xecfg);
 
-xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg);
+xdchange_t *xdl_get_hunk(xdfenv_t *xe, xdchange_t **xscr,
+                        xdemitconf_t const *xecfg);
+
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                  xdemitconf_t const *xecfg);
 
-- 
1.7.12.4 (Apple Git-37)

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to