Skip to content

Commit 60ecac9

Browse files
René Scharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2944e4e commit 60ecac9

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

Documentation/git-grep.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ OPTIONS
126126
--show-function::
127127
Show the preceding line that contains the function name of
128128
the match, unless the matching line is a function name itself.
129+
The name is determined in the same way as 'git diff' works out
130+
patch hunk headers (see 'Defining a custom hunk-header' in
131+
linkgit:gitattributes[5]).
129132

130133
-f <file>::
131134
Read patterns from <file>, one per line.

builtin-grep.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "tree-walk.h"
1212
#include "builtin.h"
1313
#include "parse-options.h"
14+
#include "userdiff.h"
1415
#include "grep.h"
1516

1617
#ifndef NO_EXTERNAL_GREP
@@ -30,6 +31,12 @@ static int grep_config(const char *var, const char *value, void *cb)
3031
{
3132
struct grep_opt *opt = cb;
3233

34+
switch (userdiff_config(var, value)) {
35+
case 0: break;
36+
case -1: return -1;
37+
default: return 0;
38+
}
39+
3340
if (!strcmp(var, "color.grep")) {
3441
opt->color = git_config_colorbool(var, value, -1);
3542
return 0;

grep.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cache.h"
22
#include "grep.h"
3+
#include "userdiff.h"
34
#include "xdiff-interface.h"
45

56
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,
535536
printf("%.*s\n", rest, bol);
536537
}
537538

538-
static int match_funcname(char *bol, char *eol)
539+
static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
539540
{
541+
xdemitconf_t *xecfg = opt->priv;
542+
if (xecfg && xecfg->find_func) {
543+
char buf[1];
544+
return xecfg->find_func(bol, eol - bol, buf, 1,
545+
xecfg->find_func_priv) >= 0;
546+
}
547+
540548
if (bol == eol)
541549
return 0;
542550
if (isalpha(*bol) || *bol == '_' || *bol == '$')
@@ -557,7 +565,7 @@ static void show_funcname_line(struct grep_opt *opt, const char *name,
557565
if (lno <= opt->last_shown)
558566
break;
559567

560-
if (match_funcname(bol, eol)) {
568+
if (match_funcname(opt, bol, eol)) {
561569
show_line(opt, bol, eol, name, lno, '=');
562570
break;
563571
}
@@ -582,7 +590,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
582590
while (bol > buf && bol[-1] != '\n')
583591
bol--;
584592
cur--;
585-
if (funcname_needed && match_funcname(bol, eol)) {
593+
if (funcname_needed && match_funcname(opt, bol, eol)) {
586594
funcname_lno = cur;
587595
funcname_needed = 0;
588596
}
@@ -614,6 +622,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
614622
int binary_match_only = 0;
615623
unsigned count = 0;
616624
enum grep_context ctx = GREP_CONTEXT_HEAD;
625+
xdemitconf_t xecfg;
617626

618627
opt->last_shown = 0;
619628

@@ -630,6 +639,17 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
630639
}
631640
}
632641

642+
memset(&xecfg, 0, sizeof(xecfg));
643+
if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
644+
!opt->name_only && !binary_match_only && !collect_hits) {
645+
struct userdiff_driver *drv = userdiff_find_by_path(name);
646+
if (drv && drv->funcname.pattern) {
647+
const struct userdiff_funcname *pe = &drv->funcname;
648+
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
649+
opt->priv = &xecfg;
650+
}
651+
}
652+
633653
while (left) {
634654
char *eol, ch;
635655
int hit;
@@ -711,6 +731,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
711731
return 1;
712732
}
713733

734+
xdiff_clear_find_func(&xecfg);
735+
opt->priv = NULL;
736+
714737
/* NEEDSWORK:
715738
* The real "grep -c foo *.c" gives many "bar.c:0" lines,
716739
* which feels mostly useless but sometimes useful. Maybe

grep.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct grep_opt {
8787
unsigned post_context;
8888
unsigned last_shown;
8989
int show_hunk_mark;
90+
void *priv;
9091
};
9192

9293
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);

t/t7002-grep.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,25 @@ test_expect_success 'grep with CE_VALID file' '
243243
git checkout t/t
244244
'
245245

246+
cat >expected <<EOF
247+
hello.c=#include <stdio.h>
248+
hello.c: return 0;
249+
EOF
250+
251+
test_expect_success 'grep -p with userdiff' '
252+
git config diff.custom.funcname "^#" &&
253+
echo "hello.c diff=custom" >.gitattributes &&
254+
git grep -p return >actual &&
255+
test_cmp expected actual
256+
'
257+
246258
cat >expected <<EOF
247259
hello.c=int main(int argc, const char **argv)
248260
hello.c: return 0;
249261
EOF
250262

251263
test_expect_success 'grep -p' '
264+
rm -f .gitattributes &&
252265
git grep -p return >actual &&
253266
test_cmp expected actual
254267
'

0 commit comments

Comments
 (0)