summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Scharfe <rene.scharfe@lsrfire.ath.cx>2009-07-02 00:07:24 +0200
committerJunio C Hamano <gitster@pobox.com>2009-07-01 19:16:50 -0700
commit60ecac98ed6f420c6bf823491074219087c749d4 (patch)
tree480471031679f5d7f88dea0c673412f1ce03890b
parent2944e4e6145bdfcb1a8730d7da671786d72c86ed (diff)
downloadgit-60ecac98ed6f420c6bf823491074219087c749d4.tar.gz
grep -p: support user defined regular expressions
Respect the userdiff attributes and config settings when looking for lines with function definitions in git grep -p. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/git-grep.txt3
-rw-r--r--builtin-grep.c7
-rw-r--r--grep.c29
-rw-r--r--grep.h1
-rwxr-xr-xt/t7002-grep.sh13
5 files changed, 50 insertions, 3 deletions
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index b3bb283644..b753c9d76f 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -126,6 +126,9 @@ OPTIONS
--show-function::
Show the preceding line that contains the function name of
the match, unless the matching line is a function name itself.
+ The name is determined in the same way as 'git diff' works out
+ patch hunk headers (see 'Defining a custom hunk-header' in
+ linkgit:gitattributes[5]).
-f <file>::
Read patterns from <file>, one per line.
diff --git a/builtin-grep.c b/builtin-grep.c
index 037452ec79..9343cc5e5d 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -11,6 +11,7 @@
#include "tree-walk.h"
#include "builtin.h"
#include "parse-options.h"
+#include "userdiff.h"
#include "grep.h"
#ifndef NO_EXTERNAL_GREP
@@ -30,6 +31,12 @@ static int grep_config(const char *var, const char *value, void *cb)
{
struct grep_opt *opt = cb;
+ switch (userdiff_config(var, value)) {
+ case 0: break;
+ case -1: return -1;
+ default: return 0;
+ }
+
if (!strcmp(var, "color.grep")) {
opt->color = git_config_colorbool(var, value, -1);
return 0;
diff --git a/grep.c b/grep.c
index 3a5c138476..c47785a2f0 100644
--- a/grep.c
+++ b/grep.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "grep.h"
+#include "userdiff.h"
#include "xdiff-interface.h"
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
@@ -535,8 +536,15 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
printf("%.*s\n", rest, bol);
}
-static int match_funcname(char *bol, char *eol)
+static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
{
+ xdemitconf_t *xecfg = opt->priv;
+ if (xecfg && xecfg->find_func) {
+ char buf[1];
+ return xecfg->find_func(bol, eol - bol, buf, 1,
+ xecfg->find_func_priv) >= 0;
+ }
+
if (bol == eol)
return 0;
if (isalpha(*bol) || *bol == '_' || *bol == '$')
@@ -557,7 +565,7 @@ static void show_funcname_line(struct grep_opt *opt, const char *name,
if (lno <= opt->last_shown)
break;
- if (match_funcname(bol, eol)) {
+ if (match_funcname(opt, bol, eol)) {
show_line(opt, bol, eol, name, lno, '=');
break;
}
@@ -582,7 +590,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
while (bol > buf && bol[-1] != '\n')
bol--;
cur--;
- if (funcname_needed && match_funcname(bol, eol)) {
+ if (funcname_needed && match_funcname(opt, bol, eol)) {
funcname_lno = cur;
funcname_needed = 0;
}
@@ -614,6 +622,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
int binary_match_only = 0;
unsigned count = 0;
enum grep_context ctx = GREP_CONTEXT_HEAD;
+ xdemitconf_t xecfg;
opt->last_shown = 0;
@@ -630,6 +639,17 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
}
}
+ memset(&xecfg, 0, sizeof(xecfg));
+ if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
+ !opt->name_only && !binary_match_only && !collect_hits) {
+ struct userdiff_driver *drv = userdiff_find_by_path(name);
+ if (drv && drv->funcname.pattern) {
+ const struct userdiff_funcname *pe = &drv->funcname;
+ xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
+ opt->priv = &xecfg;
+ }
+ }
+
while (left) {
char *eol, ch;
int hit;
@@ -711,6 +731,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
return 1;
}
+ xdiff_clear_find_func(&xecfg);
+ opt->priv = NULL;
+
/* NEEDSWORK:
* The real "grep -c foo *.c" gives many "bar.c:0" lines,
* which feels mostly useless but sometimes useful. Maybe
diff --git a/grep.h b/grep.h
index 3f75e3a3d4..f00db0e402 100644
--- a/grep.h
+++ b/grep.h
@@ -87,6 +87,7 @@ struct grep_opt {
unsigned post_context;
unsigned last_shown;
int show_hunk_mark;
+ void *priv;
};
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index ef59ab9941..b13aa7e89a 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -244,11 +244,24 @@ test_expect_success 'grep with CE_VALID file' '
'
cat >expected <<EOF
+hello.c=#include <stdio.h>
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p with userdiff' '
+ git config diff.custom.funcname "^#" &&
+ echo "hello.c diff=custom" >.gitattributes &&
+ git grep -p return >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
hello.c=int main(int argc, const char **argv)
hello.c: return 0;
EOF
test_expect_success 'grep -p' '
+ rm -f .gitattributes &&
git grep -p return >actual &&
test_cmp expected actual
'