Subject: Re: [PATCH/RFC v2] grep: Add --[no-]recurse options.

From: René Scharfe <[email-masked]>
Date: Sun, 12 Jul 2009 11:39:50 +0200

Michał Kiedrowicz schrieb:
> Sometimes it is useful to grep directories non-recursive. E.g. if I want
> to look for all files in main directory, but not in any subdirectory.
> Or in Documentation/, but not in Documentation/technical/ and so on.
> 
> This patch adds support for --no-recurse and (for symmetry) --recurse
> options to git-grep. If --no-recurse is set, git-grep does not descend
> to subdirectories. When --recurse option is set, directories are
> searched recursively (this is the default behavior).
> 
> If path specified on command line contains wildcards, option --no-recurse
> makes no sense, i.e.
> 
> $ git grep -l --no-recurse 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 <[email-masked]>
> ---
> 
> Changes from previous version:
>  * Renamed '--directories=action' to '--[no-]recurse', because my
>    implementation is not compatible with GNU. Also parsing this option was
>    simplified.

OK.  Yet another idea: if we can't copy an option from grep, perhaps we
can steal it from another program?  Would find's -maxdepth option fit
the bill?  I imagine it git grep --max-depth=<n> counting the slashes in
path specs and files and rejecting those files whose count is higher
than the one of its (otherwise matching) pattern plus n.

> diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
> index b13aa7e..0633673 100755
> --- a/t/t7002-grep.sh
> +++ b/t/t7002-grep.sh
> @@ -31,7 +31,9 @@ test_expect_success setup '
>  	echo zzz > z &&
>  	mkdir t &&
>  	echo test >t/t &&
> -	git add file w x y z t/t hello.c &&
> +	mkdir t/a &&
> +	echo aa aa aa aa >t/a/a &&
> +	git add file w x y z t/t t/a/a hello.c &&
>  	test_tick &&
>  	git commit -m initial
>  '
> @@ -132,6 +134,36 @@ do
>  		! git grep -c test $H | grep /dev/null
>          '
>  
> +	test_expect_success "grep --recurse $L" '
> +		echo "${HC}t/t:1:test" >expected &&
> +		git grep --recurse -n -e test $H >actual &&
> +		diff expected actual
> +	'

Use test_cmp instead of diff.

> +
> +	test_expect_success "grep --no-recurse $L" '
> +		: >expected &&
> +		if git grep --no-recurse -e test $H >actual
> +		then
> +			echo should not have matched
> +			cat actual
> +			false
> +		else
> +			diff expected actual
> +		fi
> +	'

Hmm, if git crashed and only wrote to stderr, this test would pass
(hint: try this with git's master, that doesn't know this option).
Better to devise a test in which the tested command still has to print
something (a restricted set of results in this case).

> +
> +	test_expect_success "grep --no-recurse $L -- t" '
> +		: >expected &&
> +		if git grep --no-recurse -e aa $H -- t >actual
> +		then
> +			echo should not have matched
> +			cat actual
> +			false
> +		else
> +			diff expected actual
> +		fi
> +	'

Same here.