Merge branch 'rs/xdiff-hunk-with-func-line' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Jun 2016 16:56:24 +0000 (09:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Jun 2016 16:56:24 +0000 (09:56 -0700)
"git show -W" (extend hunks to cover the entire function, delimited
by lines that match the "funcname" pattern) used to show the entire
file when a change added an entire function at the end of the file,
which has been fixed.

* rs/xdiff-hunk-with-func-line:
xdiff: fix merging of appended hunk with -W
grep: -W: don't extend context to trailing empty lines
t7810: add test for grep -W and trailing empty context lines
xdiff: don't trim common tail with -W
xdiff: -W: don't include common trailing empty lines in context
xdiff: ignore empty lines before added functions with -W
xdiff: handle appended chunks better with -W
xdiff: factor out match_func_rec()
t4051: rewrite, add more tests

1  2 
grep.c
t/t7810-grep.sh
diff --combined grep.c
index ec6f7ffa19622f1a63a4cdd51936d1061e90fc49,fafb8b58e08282e70f97676784bcb7e23e776490..1e15b6292d768e9daf5c5e84f9346577abdf3939
--- 1/grep.c
--- 2/grep.c
+++ b/grep.c
@@@ -1396,9 -1396,17 +1396,17 @@@ static int fill_textconv_grep(struct us
        return 0;
  }
  
+ static int is_empty_line(const char *bol, const char *eol)
+ {
+       while (bol < eol && isspace(*bol))
+               bol++;
+       return bol == eol;
+ }
  static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int collect_hits)
  {
        char *bol;
+       char *peek_bol = NULL;
        unsigned long left;
        unsigned lno = 1;
        unsigned last_hit = 0;
                                show_function = 1;
                        goto next_line;
                }
-               if (show_function && match_funcname(opt, gs, bol, eol))
-                       show_function = 0;
+               if (show_function && (!peek_bol || peek_bol < bol)) {
+                       unsigned long peek_left = left;
+                       char *peek_eol = eol;
+                       /*
+                        * Trailing empty lines are not interesting.
+                        * Peek past them to see if they belong to the
+                        * body of the current function.
+                        */
+                       peek_bol = bol;
+                       while (is_empty_line(peek_bol, peek_eol)) {
+                               peek_bol = peek_eol + 1;
+                               peek_eol = end_of_line(peek_bol, &peek_left);
+                       }
+                       if (match_funcname(opt, gs, peek_bol, peek_eol))
+                               show_function = 0;
+               }
                if (show_function ||
                    (last_hit && lno <= last_hit + opt->post_context)) {
                        /* If the last hit is within the post context,
@@@ -1732,7 -1756,7 +1756,7 @@@ static int grep_source_load_file(struc
        if (lstat(filename, &st) < 0) {
        err_ret:
                if (errno != ENOENT)
 -                      error(_("'%s': %s"), filename, strerror(errno));
 +                      error_errno(_("failed to stat '%s'"), filename);
                return -1;
        }
        if (!S_ISREG(st.st_mode))
                goto err_ret;
        data = xmallocz(size);
        if (st.st_size != read_in_full(i, data, size)) {
 -              error(_("'%s': short read %s"), filename, strerror(errno));
 +              error_errno(_("'%s': short read"), filename);
                close(i);
                free(data);
                return -1;
diff --combined t/t7810-grep.sh
index 1e72971a165efc127e6bda24fb0e4a3852d3c543,befbde44f41f5bf3d3eec3351dd49da5f6dc5514..960425a4ec6229cd2d15dac74f6fdf6deda4ec6c
@@@ -9,7 -9,9 +9,9 @@@ test_description='git grep various
  . ./test-lib.sh
  
  cat >hello.c <<EOF
+ #include <assert.h>
  #include <stdio.h>
  int main(int argc, const char **argv)
  {
        printf("Hello world.\n");
@@@ -715,6 -717,7 +717,7 @@@ test_expect_success 'grep -p' 
  
  cat >expected <<EOF
  hello.c-#include <stdio.h>
+ hello.c-
  hello.c=int main(int argc, const char **argv)
  hello.c-{
  hello.c-      printf("Hello world.\n");
@@@ -740,6 -743,16 +743,16 @@@ test_expect_success 'grep -W' 
        test_cmp expected actual
  '
  
+ cat >expected <<EOF
+ hello.c-#include <assert.h>
+ hello.c:#include <stdio.h>
+ EOF
+ test_expect_success 'grep -W shows no trailing empty lines' '
+       git grep -W stdio >actual &&
+       test_cmp expected actual
+ '
  cat >expected <<EOF
  hello.c=      printf("Hello world.\n");
  hello.c:      return 0;
@@@ -905,33 -918,6 +918,33 @@@ test_expect_success 'inside git reposit
        )
  '
  
 +test_expect_success 'grep --no-index descends into repos, but not .git' '
 +      rm -fr non &&
 +      mkdir -p non/git &&
 +      (
 +              GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
 +              export GIT_CEILING_DIRECTORIES &&
 +              cd non/git &&
 +
 +              echo magic >file &&
 +              git init repo &&
 +              (
 +                      cd repo &&
 +                      echo magic >file &&
 +                      git add file &&
 +                      git commit -m foo &&
 +                      echo magic >.git/file
 +              ) &&
 +
 +              cat >expect <<-\EOF &&
 +              file
 +              repo/file
 +              EOF
 +              git grep -l --no-index magic >actual &&
 +              test_cmp expect actual
 +      )
 +'
 +
  test_expect_success 'setup double-dash tests' '
  cat >double-dash <<EOF &&
  --
@@@ -1232,8 -1218,8 +1245,8 @@@ test_expect_success 'grep --heading' 
  
  cat >expected <<EOF
  <BOLD;GREEN>hello.c<RESET>
2:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv)
6:    /* <BLACK;BYELLOW>char<RESET> ?? */
4:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv)
8:    /* <BLACK;BYELLOW>char<RESET> ?? */
  
  <BOLD;GREEN>hello_world<RESET>
  3:Hel<BLACK;BYELLOW>lo_w<RESET>orld
@@@ -1340,7 -1326,7 +1353,7 @@@ test_expect_success 'grep --color -e A 
  '
  
  cat >expected <<EOF
- hello.c-#include <stdio.h>
+ hello.c-
  hello.c=int main(int argc, const char **argv)
  hello.c-{
  hello.c:      pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");