mirror of
https://github.com/git/git.git
synced 2024-12-18 06:14:59 +08:00
Fix "grep -w"
We used to find the first match of the pattern and then if the match is not for the entire word, declared that the whole line does not match. But that is wrong. The command "git grep -w -e mmap" should find that a line "foo_mmap bar mmap baz" matches, by tring the second instance of pattern "mmap" on the same line. Problems an earlier round of "fix" had were pointed out by Morten Welinder, which have been incorporated in the t7002 tests. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
0d958ac47a
commit
f25b79397c
@ -410,8 +410,10 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
|
||||
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol)
|
||||
{
|
||||
int hit = 0;
|
||||
int at_true_bol = 1;
|
||||
regmatch_t pmatch[10];
|
||||
|
||||
again:
|
||||
if (!opt->fixed) {
|
||||
regex_t *exp = &p->regexp;
|
||||
hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
|
||||
@ -422,22 +424,35 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
|
||||
}
|
||||
|
||||
if (hit && opt->word_regexp) {
|
||||
/* Match beginning must be either
|
||||
* beginning of the line, or at word
|
||||
* boundary (i.e. the last char must
|
||||
* not be alnum or underscore).
|
||||
*/
|
||||
if ((pmatch[0].rm_so < 0) ||
|
||||
(eol - bol) <= pmatch[0].rm_so ||
|
||||
(pmatch[0].rm_eo < 0) ||
|
||||
(eol - bol) < pmatch[0].rm_eo)
|
||||
die("regexp returned nonsense");
|
||||
if (pmatch[0].rm_so != 0 &&
|
||||
word_char(bol[pmatch[0].rm_so-1]))
|
||||
hit = 0;
|
||||
if (pmatch[0].rm_eo != (eol-bol) &&
|
||||
word_char(bol[pmatch[0].rm_eo]))
|
||||
|
||||
/* Match beginning must be either beginning of the
|
||||
* line, or at word boundary (i.e. the last char must
|
||||
* not be a word char). Similarly, match end must be
|
||||
* either end of the line, or at word boundary
|
||||
* (i.e. the next char must not be a word char).
|
||||
*/
|
||||
if ( ((pmatch[0].rm_so == 0 && at_true_bol) ||
|
||||
!word_char(bol[pmatch[0].rm_so-1])) &&
|
||||
((pmatch[0].rm_eo == (eol-bol)) ||
|
||||
!word_char(bol[pmatch[0].rm_eo])) )
|
||||
;
|
||||
else
|
||||
hit = 0;
|
||||
|
||||
if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
|
||||
/* There could be more than one match on the
|
||||
* line, and the first match might not be
|
||||
* strict word match. But later ones could be!
|
||||
*/
|
||||
bol = pmatch[0].rm_so + bol + 1;
|
||||
at_true_bol = 0;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
85
t/t7002-grep.sh
Executable file
85
t/t7002-grep.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006 Junio C Hamano
|
||||
#
|
||||
|
||||
test_description='git grep -w
|
||||
'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
{
|
||||
echo foo mmap bar
|
||||
echo foo_mmap bar
|
||||
echo foo_mmap bar mmap
|
||||
echo foo mmap bar_mmap
|
||||
echo foo_mmap bar mmap baz
|
||||
} >file &&
|
||||
echo x x xx x >x &&
|
||||
echo y yy >y &&
|
||||
echo zzz > z &&
|
||||
git add file x y z &&
|
||||
git commit -m initial
|
||||
'
|
||||
|
||||
for H in HEAD ''
|
||||
do
|
||||
case "$H" in
|
||||
HEAD) HC='HEAD:' L='HEAD' ;;
|
||||
'') HC= L='in working tree' ;;
|
||||
esac
|
||||
|
||||
test_expect_success "grep -w $L" '
|
||||
{
|
||||
echo ${HC}file:1:foo mmap bar
|
||||
echo ${HC}file:3:foo_mmap bar mmap
|
||||
echo ${HC}file:4:foo mmap bar_mmap
|
||||
echo ${HC}file:5:foo_mmap bar mmap baz
|
||||
} >expected &&
|
||||
git grep -n -w -e mmap $H >actual &&
|
||||
diff expected actual
|
||||
'
|
||||
|
||||
test_expect_success "grep -w $L (x)" '
|
||||
{
|
||||
echo ${HC}x:1:x x xx x
|
||||
} >expected &&
|
||||
git grep -n -w -e "x xx* x" $H >actual &&
|
||||
diff expected actual
|
||||
'
|
||||
|
||||
test_expect_success "grep -w $L (y-1)" '
|
||||
{
|
||||
echo ${HC}y:1:y yy
|
||||
} >expected &&
|
||||
git grep -n -w -e "^y" $H >actual &&
|
||||
diff expected actual
|
||||
'
|
||||
|
||||
test_expect_success "grep -w $L (y-2)" '
|
||||
: >expected &&
|
||||
if git grep -n -w -e "^y y" $H >actual
|
||||
then
|
||||
echo should not have matched
|
||||
cat actual
|
||||
false
|
||||
else
|
||||
diff expected actual
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success "grep -w $L (z)" '
|
||||
: >expected &&
|
||||
if git grep -n -w -e "^z" $H >actual
|
||||
then
|
||||
echo should not have matched
|
||||
cat actual
|
||||
false
|
||||
else
|
||||
diff expected actual
|
||||
fi
|
||||
'
|
||||
done
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user