If lines are added at the end of a file, diff -W shows the whole file.
That's because get_func_line() only considers the pre-image and gives up
if it sees a record index beyond its end.

Consider the post-image as well to see if the added lines already make
up a full function.  If it doesn't then search for the previous function
line by starting from the bottom of the pre-image, thereby avoiding to
confuse get_func_line().

Reuse the existing label called "again", as it's exactly where we need
to jump to when we're done handling the pre-context, but rename it to
"post_context_calculation" in order to document its new purpose better.

Reported-by: Junio C Hamano <gits...@pobox.com>
Initial-patch-by: Junio C Hamano <gits...@pobox.com>
Signed-off-by: Rene Scharfe <l....@web.de>
---
 t/t4051-diff-function-context.sh |  2 +-
 xdiff/xemit.c                    | 27 ++++++++++++++++++++++++---
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/t/t4051-diff-function-context.sh b/t/t4051-diff-function-context.sh
index a3adba4..d78461d 100755
--- a/t/t4051-diff-function-context.sh
+++ b/t/t4051-diff-function-context.sh
@@ -131,7 +131,7 @@ test_expect_success ' context includes end' '
        grep "^[+].*End of second part" extended.diff
 '
 
-test_expect_failure ' context does not include other functions' '
+test_expect_success ' context does not include other functions' '
        test $(grep -c "^[ +-].*Begin" extended.diff) -le 2
 '
 
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index 0c87637..969100d 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -171,7 +171,28 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, 
xdemitcb_t *ecb,
                s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
 
                if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
-                       long fs1 = get_func_line(xe, xecfg, NULL, xch->i1, -1);
+                       long fs1, i1 = xch->i1;
+
+                       /* Appended chunk? */
+                       if (i1 >= xe->xdf1.nrec) {
+                               char dummy[1];
+
+                               /*
+                                * We don't need additional context if
+                                * a whole function was added.
+                                */
+                               if (match_func_rec(&xe->xdf2, xecfg, xch->i2,
+                                                  dummy, sizeof(dummy)) >= 0)
+                                       goto post_context_calculation;
+
+                               /*
+                                * Otherwise get more context from the
+                                * pre-image.
+                                */
+                               i1 = xe->xdf1.nrec - 1;
+                       }
+
+                       fs1 = get_func_line(xe, xecfg, NULL, i1, -1);
                        if (fs1 < 0)
                                fs1 = 0;
                        if (fs1 < s1) {
@@ -180,7 +201,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, 
xdemitcb_t *ecb,
                        }
                }
 
- again:
+ post_context_calculation:
                lctx = xecfg->ctxlen;
                lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1));
                lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2));
@@ -209,7 +230,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, 
xdemitcb_t *ecb,
                                if (l <= e1 ||
                                    get_func_line(xe, xecfg, NULL, l, e1) < 0) {
                                        xche = xche->next;
-                                       goto again;
+                                       goto post_context_calculation;
                                }
                        }
                }
-- 
2.8.3

--
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