2006-08-05 13:16:42 +08:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (c) 2006 Junio C Hamano
|
|
|
|
#
|
|
|
|
|
2006-08-11 15:44:42 +08:00
|
|
|
test_description='git grep various.
|
2006-08-05 13:16:42 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
2009-07-02 06:06:34 +08:00
|
|
|
cat >hello.c <<EOF
|
|
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, const char **argv)
|
|
|
|
{
|
|
|
|
printf("Hello world.\n");
|
|
|
|
return 0;
|
2009-11-06 17:22:35 +08:00
|
|
|
/* char ?? */
|
2009-07-02 06:06:34 +08:00
|
|
|
}
|
|
|
|
EOF
|
|
|
|
|
2006-08-05 13:16:42 +08:00
|
|
|
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 &&
|
grep: Add --max-depth option.
It is useful to grep directories non-recursively, e.g. when one wants to
look for all files in the toplevel directory, but not in any subdirectory,
or in Documentation/, but not in Documentation/technical/.
This patch adds support for --max-depth <depth> option to git-grep. If it is
given, git-grep descends at most <depth> levels of directories below paths
specified on the command line.
Note that if path specified on command line contains wildcards, this option
makes no sense, e.g.
$ git grep -l --max-depth 0 GNU -- 'contrib/*'
(note the quotes) will search all files in contrib/, even in
subdirectories, because '*' matches all files.
Documentation updates, bash-completion and simple test cases are also
provided.
Signed-off-by: Michał Kiedrowicz <michal.kiedrowicz@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-23 01:52:15 +08:00
|
|
|
echo vvv >v &&
|
2009-05-23 19:45:26 +08:00
|
|
|
echo ww w >w &&
|
2006-08-05 13:16:42 +08:00
|
|
|
echo x x xx x >x &&
|
|
|
|
echo y yy >y &&
|
|
|
|
echo zzz > z &&
|
2006-08-11 15:44:42 +08:00
|
|
|
mkdir t &&
|
|
|
|
echo test >t/t &&
|
grep: Add --max-depth option.
It is useful to grep directories non-recursively, e.g. when one wants to
look for all files in the toplevel directory, but not in any subdirectory,
or in Documentation/, but not in Documentation/technical/.
This patch adds support for --max-depth <depth> option to git-grep. If it is
given, git-grep descends at most <depth> levels of directories below paths
specified on the command line.
Note that if path specified on command line contains wildcards, this option
makes no sense, e.g.
$ git grep -l --max-depth 0 GNU -- 'contrib/*'
(note the quotes) will search all files in contrib/, even in
subdirectories, because '*' matches all files.
Documentation updates, bash-completion and simple test cases are also
provided.
Signed-off-by: Michał Kiedrowicz <michal.kiedrowicz@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-23 01:52:15 +08:00
|
|
|
echo vvv >t/v &&
|
|
|
|
mkdir t/a &&
|
|
|
|
echo vvv >t/a/v &&
|
|
|
|
git add . &&
|
log --author/--committer: really match only with name part
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-09-05 13:15:02 +08:00
|
|
|
test_tick &&
|
2006-08-05 13:16:42 +08:00
|
|
|
git commit -m initial
|
|
|
|
'
|
|
|
|
|
2009-04-28 02:10:24 +08:00
|
|
|
test_expect_success 'grep should not segfault with a bad input' '
|
|
|
|
test_must_fail git grep "("
|
|
|
|
'
|
|
|
|
|
2006-08-05 13:16:42 +08:00
|
|
|
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 &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-05 13:16:42 +08:00
|
|
|
'
|
|
|
|
|
2009-05-23 19:45:26 +08:00
|
|
|
test_expect_success "grep -w $L (w)" '
|
|
|
|
: >expected &&
|
|
|
|
! git grep -n -w -e "^w" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2006-08-05 13:16:42 +08:00
|
|
|
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 &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-05 13:16:42 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep -w $L (y-1)" '
|
|
|
|
{
|
|
|
|
echo ${HC}y:1:y yy
|
|
|
|
} >expected &&
|
|
|
|
git grep -n -w -e "^y" $H >actual &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-05 13:16:42 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
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
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-05 13:16:42 +08:00
|
|
|
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
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-05 13:16:42 +08:00
|
|
|
fi
|
|
|
|
'
|
2006-08-11 15:44:42 +08:00
|
|
|
|
|
|
|
test_expect_success "grep $L (t-1)" '
|
|
|
|
echo "${HC}t/t:1:test" >expected &&
|
|
|
|
git grep -n -e test $H >actual &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-11 15:44:42 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep $L (t-2)" '
|
|
|
|
echo "${HC}t:1:test" >expected &&
|
|
|
|
(
|
|
|
|
cd t &&
|
|
|
|
git grep -n -e test $H
|
|
|
|
) >actual &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-11 15:44:42 +08:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep $L (t-3)" '
|
|
|
|
echo "${HC}t/t:1:test" >expected &&
|
|
|
|
(
|
|
|
|
cd t &&
|
|
|
|
git grep --full-name -n -e test $H
|
|
|
|
) >actual &&
|
2010-05-14 17:31:37 +08:00
|
|
|
test_cmp expected actual
|
2006-08-11 15:44:42 +08:00
|
|
|
'
|
|
|
|
|
2008-02-01 17:50:53 +08:00
|
|
|
test_expect_success "grep -c $L (no /dev/null)" '
|
2008-09-30 16:03:55 +08:00
|
|
|
! git grep -c test $H | grep /dev/null
|
2007-09-14 15:31:00 +08:00
|
|
|
'
|
|
|
|
|
grep: Add --max-depth option.
It is useful to grep directories non-recursively, e.g. when one wants to
look for all files in the toplevel directory, but not in any subdirectory,
or in Documentation/, but not in Documentation/technical/.
This patch adds support for --max-depth <depth> option to git-grep. If it is
given, git-grep descends at most <depth> levels of directories below paths
specified on the command line.
Note that if path specified on command line contains wildcards, this option
makes no sense, e.g.
$ git grep -l --max-depth 0 GNU -- 'contrib/*'
(note the quotes) will search all files in contrib/, even in
subdirectories, because '*' matches all files.
Documentation updates, bash-completion and simple test cases are also
provided.
Signed-off-by: Michał Kiedrowicz <michal.kiedrowicz@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-23 01:52:15 +08:00
|
|
|
test_expect_success "grep --max-depth -1 $L" '
|
|
|
|
{
|
|
|
|
echo ${HC}t/a/v:1:vvv
|
|
|
|
echo ${HC}t/v:1:vvv
|
|
|
|
echo ${HC}v:1:vvv
|
|
|
|
} >expected &&
|
|
|
|
git grep --max-depth -1 -n -e vvv $H >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep --max-depth 0 $L" '
|
|
|
|
{
|
|
|
|
echo ${HC}v:1:vvv
|
|
|
|
} >expected &&
|
|
|
|
git grep --max-depth 0 -n -e vvv $H >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep --max-depth 0 -- '*' $L" '
|
|
|
|
{
|
|
|
|
echo ${HC}t/a/v:1:vvv
|
|
|
|
echo ${HC}t/v:1:vvv
|
|
|
|
echo ${HC}v:1:vvv
|
|
|
|
} >expected &&
|
|
|
|
git grep --max-depth 0 -n -e vvv $H -- "*" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep --max-depth 1 $L" '
|
|
|
|
{
|
|
|
|
echo ${HC}t/v:1:vvv
|
|
|
|
echo ${HC}v:1:vvv
|
|
|
|
} >expected &&
|
|
|
|
git grep --max-depth 1 -n -e vvv $H >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success "grep --max-depth 0 -- t $L" '
|
|
|
|
{
|
|
|
|
echo ${HC}t/v:1:vvv
|
|
|
|
} >expected &&
|
|
|
|
git grep --max-depth 0 -n -e vvv $H -- t >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2006-08-05 13:16:42 +08:00
|
|
|
done
|
|
|
|
|
2009-06-28 02:47:44 +08:00
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo mmap bar_mmap
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -e A --and -e B' '
|
|
|
|
git grep -e "foo mmap" --and -e bar_mmap >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo_mmap bar mmap
|
|
|
|
file:foo_mmap bar mmap baz
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
test_expect_success 'grep ( -e A --or -e B ) --and -e B' '
|
|
|
|
git grep \( -e foo_ --or -e baz \) \
|
|
|
|
--and -e " mmap" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo mmap bar
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -e A --and --not -e B' '
|
|
|
|
git grep -e "foo mmap" --and --not -e bar_mmap >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2009-11-22 23:58:09 +08:00
|
|
|
test_expect_success 'grep should ignore GREP_OPTIONS' '
|
|
|
|
GREP_OPTIONS=-v git grep " mmap bar\$" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2009-10-16 22:13:25 +08:00
|
|
|
test_expect_success 'grep -f, non-existent file' '
|
|
|
|
test_must_fail git grep -f patterns
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo mmap bar
|
|
|
|
file:foo_mmap bar
|
|
|
|
file:foo_mmap bar mmap
|
|
|
|
file:foo mmap bar_mmap
|
|
|
|
file:foo_mmap bar mmap baz
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat >pattern <<EOF
|
|
|
|
mmap
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -f, one pattern' '
|
|
|
|
git grep -f pattern >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo mmap bar
|
|
|
|
file:foo_mmap bar
|
|
|
|
file:foo_mmap bar mmap
|
|
|
|
file:foo mmap bar_mmap
|
|
|
|
file:foo_mmap bar mmap baz
|
|
|
|
t/a/v:vvv
|
|
|
|
t/v:vvv
|
|
|
|
v:vvv
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat >patterns <<EOF
|
|
|
|
mmap
|
|
|
|
vvv
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -f, multiple patterns' '
|
|
|
|
git grep -f patterns >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
file:foo mmap bar
|
|
|
|
file:foo_mmap bar
|
|
|
|
file:foo_mmap bar mmap
|
|
|
|
file:foo mmap bar_mmap
|
|
|
|
file:foo_mmap bar mmap baz
|
|
|
|
t/a/v:vvv
|
|
|
|
t/v:vvv
|
|
|
|
v:vvv
|
|
|
|
EOF
|
|
|
|
|
|
|
|
cat >patterns <<EOF
|
|
|
|
|
|
|
|
mmap
|
|
|
|
|
|
|
|
vvv
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -f, ignore empty lines' '
|
|
|
|
git grep -f patterns >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2009-07-02 06:03:44 +08:00
|
|
|
cat >expected <<EOF
|
|
|
|
y:y yy
|
|
|
|
--
|
|
|
|
z:zzz
|
|
|
|
EOF
|
|
|
|
|
2010-01-29 04:33:42 +08:00
|
|
|
test_expect_success 'grep -q, silently report matches' '
|
|
|
|
>empty &&
|
|
|
|
git grep -q mmap >actual &&
|
|
|
|
test_cmp empty actual &&
|
|
|
|
test_must_fail git grep -q qfwfq >actual &&
|
|
|
|
test_cmp empty actual
|
|
|
|
'
|
|
|
|
|
2009-07-02 06:03:44 +08:00
|
|
|
# Create 1024 file names that sort between "y" and "z" to make sure
|
|
|
|
# the two files are handled by different calls to an external grep.
|
|
|
|
# This depends on MAXARGS in builtin-grep.c being 1024 or less.
|
|
|
|
c32="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v"
|
|
|
|
test_expect_success 'grep -C1, hunk mark between files' '
|
|
|
|
for a in $c32; do for b in $c32; do : >y-$a$b; done; done &&
|
|
|
|
git add y-?? &&
|
|
|
|
git grep -C1 "^[yz]" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2010-01-13 11:06:41 +08:00
|
|
|
test_expect_success 'grep -C1 hunk mark between files' '
|
|
|
|
git grep -C1 "^[yz]" >actual &&
|
2009-07-02 06:03:44 +08:00
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
log --author/--committer: really match only with name part
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-09-05 13:15:02 +08:00
|
|
|
test_expect_success 'log grep setup' '
|
|
|
|
echo a >>file &&
|
|
|
|
test_tick &&
|
|
|
|
GIT_AUTHOR_NAME="With * Asterisk" \
|
|
|
|
GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
|
|
|
|
git commit -a -m "second" &&
|
|
|
|
|
|
|
|
echo a >>file &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -a -m "third"
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (1)' '
|
|
|
|
git log --author=author --pretty=tformat:%s >actual &&
|
|
|
|
( echo third ; echo initial ) >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (2)' '
|
|
|
|
git log --author=" * " -F --pretty=tformat:%s >actual &&
|
|
|
|
( echo second ) >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (3)' '
|
|
|
|
git log --author="^A U" --pretty=tformat:%s >actual &&
|
|
|
|
( echo third ; echo initial ) >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (4)' '
|
|
|
|
git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
|
|
|
|
( echo second ) >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (5)' '
|
"log --author=me --grep=it" should find intersection, not union
Historically, any grep filter in "git log" family of commands were taken
as restricting to commits with any of the words in the commit log message.
However, the user almost always want to find commits "done by this person
on that topic". With "--all-match" option, a series of grep patterns can
be turned into a requirement that all of them must produce a match, but
that makes it impossible to ask for "done by me, on either this or that"
with:
log --author=me --committer=him --grep=this --grep=that
because it will require both "this" and "that" to appear.
Change the "header" parser of grep library to treat the headers specially,
and parse it as:
(all-match-OR (HEADER-AUTHOR me)
(HEADER-COMMITTER him)
(OR
(PATTERN this)
(PATTERN that) ) )
Even though the "log" command line parser doesn't give direct access to
the extended grep syntax to group terms with parentheses, this change will
cover the majority of the case the users would want.
This incidentally revealed that one test in t7002 was bogus. It ran:
log --author=Thor --grep=Thu --format='%s'
and expected (wrongly) "Thu" to match "Thursday" in the author/committer
date, but that would never match, as the timestamp in raw commit buffer
does not have the name of the day-of-the-week.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-18 12:09:06 +08:00
|
|
|
git log --author=Thor -F --pretty=tformat:%s >actual &&
|
log --author/--committer: really match only with name part
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-09-05 13:15:02 +08:00
|
|
|
( echo third ; echo initial ) >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'log grep (6)' '
|
|
|
|
git log --author=-0700 --pretty=tformat:%s >actual &&
|
|
|
|
>expect &&
|
|
|
|
test_cmp expect actual
|
2008-12-27 16:21:03 +08:00
|
|
|
'
|
log --author/--committer: really match only with name part
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-09-05 13:15:02 +08:00
|
|
|
|
"log --author=me --grep=it" should find intersection, not union
Historically, any grep filter in "git log" family of commands were taken
as restricting to commits with any of the words in the commit log message.
However, the user almost always want to find commits "done by this person
on that topic". With "--all-match" option, a series of grep patterns can
be turned into a requirement that all of them must produce a match, but
that makes it impossible to ask for "done by me, on either this or that"
with:
log --author=me --committer=him --grep=this --grep=that
because it will require both "this" and "that" to appear.
Change the "header" parser of grep library to treat the headers specially,
and parse it as:
(all-match-OR (HEADER-AUTHOR me)
(HEADER-COMMITTER him)
(OR
(PATTERN this)
(PATTERN that) ) )
Even though the "log" command line parser doesn't give direct access to
the extended grep syntax to group terms with parentheses, this change will
cover the majority of the case the users would want.
This incidentally revealed that one test in t7002 was bogus. It ran:
log --author=Thor --grep=Thu --format='%s'
and expected (wrongly) "Thu" to match "Thursday" in the author/committer
date, but that would never match, as the timestamp in raw commit buffer
does not have the name of the day-of-the-week.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-18 12:09:06 +08:00
|
|
|
test_expect_success 'log --grep --author implicitly uses all-match' '
|
|
|
|
# grep matches initial and second but not third
|
|
|
|
# author matches only initial and third
|
|
|
|
git log --author="A U Thor" --grep=s --grep=l --format=%s >actual &&
|
|
|
|
echo initial >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2008-12-27 16:21:03 +08:00
|
|
|
test_expect_success 'grep with CE_VALID file' '
|
|
|
|
git update-index --assume-unchanged t/t &&
|
|
|
|
rm t/t &&
|
2010-01-13 11:06:41 +08:00
|
|
|
test "$(git grep test)" = "t/t:test" &&
|
2008-12-27 16:21:03 +08:00
|
|
|
git update-index --no-assume-unchanged t/t &&
|
|
|
|
git checkout t/t
|
log --author/--committer: really match only with name part
When we tried to find commits done by AUTHOR, the first implementation
tried to pattern match a line with "^author .*AUTHOR", which later was
enhanced to strip leading caret and look for "^author AUTHOR" when the
search pattern was anchored at the left end (i.e. --author="^AUTHOR").
This had a few problems:
* When looking for fixed strings (e.g. "git log -F --author=x --grep=y"),
the regexp internally used "^author .*x" would never match anything;
* To match at the end (e.g. "git log --author='google.com>$'"), the
generated regexp has to also match the trailing timestamp part the
commit header lines have. Also, in order to determine if the '$' at
the end means "match at the end of the line" or just a literal dollar
sign (probably backslash-quoted), we would need to parse the regexp
ourselves.
An earlier alternative tried to make sure that a line matches "^author "
(to limit by field name) and the user supplied pattern at the same time.
While it solved the -F problem by introducing a special override for
matching the "^author ", it did not solve the trailing timestamp nor tail
match problem. It also would have matched every commit if --author=author
was asked for, not because the author's email part had this string, but
because every commit header line that talks about the author begins with
that field name, regardleses of who wrote it.
Instead of piling more hacks on top of hacks, this rethinks the grep
machinery that is used to look for strings in the commit header, and makes
sure that (1) field name matches literally at the beginning of the line,
followed by a SP, and (2) the user supplied pattern is matched against the
remainder of the line, excluding the trailing timestamp data.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-09-05 13:15:02 +08:00
|
|
|
'
|
|
|
|
|
2009-07-02 06:07:24 +08:00
|
|
|
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
|
|
|
|
'
|
|
|
|
|
2009-07-02 06:06:34 +08:00
|
|
|
cat >expected <<EOF
|
|
|
|
hello.c=int main(int argc, const char **argv)
|
|
|
|
hello.c: return 0;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -p' '
|
2009-07-02 06:07:24 +08:00
|
|
|
rm -f .gitattributes &&
|
2009-07-02 06:06:34 +08:00
|
|
|
git grep -p return >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
hello.c-#include <stdio.h>
|
|
|
|
hello.c=int main(int argc, const char **argv)
|
|
|
|
hello.c-{
|
|
|
|
hello.c- printf("Hello world.\n");
|
|
|
|
hello.c: return 0;
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -p -B5' '
|
|
|
|
git grep -p -B5 return >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2009-09-05 20:31:17 +08:00
|
|
|
test_expect_success 'grep from a subdirectory to search wider area (1)' '
|
|
|
|
mkdir -p s &&
|
|
|
|
(
|
|
|
|
cd s && git grep "x x x" ..
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'grep from a subdirectory to search wider area (2)' '
|
|
|
|
mkdir -p s &&
|
|
|
|
(
|
|
|
|
cd s || exit 1
|
|
|
|
( git grep xxyyzz .. >out ; echo $? >status )
|
|
|
|
! test -s out &&
|
|
|
|
test 1 = $(cat status)
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2009-11-06 17:22:35 +08:00
|
|
|
cat >expected <<EOF
|
|
|
|
hello.c:int main(int argc, const char **argv)
|
|
|
|
EOF
|
|
|
|
|
|
|
|
test_expect_success 'grep -Fi' '
|
|
|
|
git grep -Fi "CHAR *" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2010-02-07 02:40:08 +08:00
|
|
|
test_expect_success 'outside of git repository' '
|
|
|
|
rm -fr non &&
|
|
|
|
mkdir -p non/git/sub &&
|
|
|
|
echo hello >non/git/file1 &&
|
|
|
|
echo world >non/git/sub/file2 &&
|
|
|
|
echo ".*o*" >non/git/.gitignore &&
|
|
|
|
{
|
|
|
|
echo file1:hello &&
|
|
|
|
echo sub/file2:world
|
|
|
|
} >non/expect.full &&
|
|
|
|
echo file2:world >non/expect.sub
|
|
|
|
(
|
|
|
|
GIT_CEILING_DIRECTORIES="$(pwd)/non/git" &&
|
|
|
|
export GIT_CEILING_DIRECTORIES &&
|
|
|
|
cd non/git &&
|
|
|
|
test_must_fail git grep o &&
|
|
|
|
git grep --no-index o >../actual.full &&
|
|
|
|
test_cmp ../expect.full ../actual.full
|
|
|
|
cd sub &&
|
|
|
|
test_must_fail git grep o &&
|
|
|
|
git grep --no-index o >../../actual.sub &&
|
|
|
|
test_cmp ../../expect.sub ../../actual.sub
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'inside git repository but with --no-index' '
|
|
|
|
rm -fr is &&
|
|
|
|
mkdir -p is/git/sub &&
|
|
|
|
echo hello >is/git/file1 &&
|
|
|
|
echo world >is/git/sub/file2 &&
|
|
|
|
echo ".*o*" >is/git/.gitignore &&
|
|
|
|
{
|
|
|
|
echo file1:hello &&
|
|
|
|
echo sub/file2:world
|
|
|
|
} >is/expect.full &&
|
|
|
|
: >is/expect.empty &&
|
|
|
|
echo file2:world >is/expect.sub
|
|
|
|
(
|
|
|
|
cd is/git &&
|
|
|
|
git init &&
|
|
|
|
test_must_fail git grep o >../actual.full &&
|
|
|
|
test_cmp ../expect.empty ../actual.full &&
|
|
|
|
git grep --no-index o >../actual.full &&
|
|
|
|
test_cmp ../expect.full ../actual.full &&
|
|
|
|
cd sub &&
|
|
|
|
test_must_fail git grep o >../../actual.sub &&
|
|
|
|
test_cmp ../../expect.empty ../../actual.sub &&
|
|
|
|
git grep --no-index o >../../actual.sub &&
|
|
|
|
test_cmp ../../expect.sub ../../actual.sub
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2010-02-07 12:44:15 +08:00
|
|
|
test_expect_success 'setup double-dash tests' '
|
|
|
|
cat >double-dash <<EOF &&
|
|
|
|
--
|
|
|
|
->
|
|
|
|
other
|
|
|
|
EOF
|
|
|
|
git add double-dash
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
double-dash:->
|
|
|
|
EOF
|
|
|
|
test_expect_success 'grep -- pattern' '
|
|
|
|
git grep -- "->" >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
test_expect_success 'grep -- pattern -- pathspec' '
|
|
|
|
git grep -- "->" -- double-dash >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
test_expect_success 'grep -e pattern -- path' '
|
|
|
|
git grep -e "->" -- double-dash >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
cat >expected <<EOF
|
|
|
|
double-dash:--
|
|
|
|
EOF
|
|
|
|
test_expect_success 'grep -e -- -- path' '
|
|
|
|
git grep -e -- -- double-dash >actual &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2006-08-05 13:16:42 +08:00
|
|
|
test_done
|