Skip to content

Commit

Permalink
grep -p: support user defined regular expressions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
René Scharfe authored and Junio C Hamano committed Jul 2, 2009
1 parent 2944e4e commit 60ecac9
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Documentation/git-grep.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions builtin-grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down
29 changes: 26 additions & 3 deletions grep.c
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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 == '$')
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions grep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions t/t7002-grep.sh
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,25 @@ test_expect_success 'grep with CE_VALID file' '
git checkout t/t
'

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
'
Expand Down

0 comments on commit 60ecac9

Please sign in to comment.