[PATCH 6/6] grep -p: support user defined regular expressions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx>
---
 Documentation/git-grep.txt |    3 +++
 builtin-grep.c             |    7 +++++++
 grep.c                     |   29 ++++++++++++++++++++++++++---
 grep.h                     |    1 +
 t/t7002-grep.sh            |   13 +++++++++++++
 5 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index b3bb283..b753c9d 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 037452e..9343cc5 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 3a5c138..c47785a 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 3f75e3a..f00db0e 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 ef59ab9..b13aa7e 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
 '
-- 
1.6.3.3

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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]