threads / rfc / 46596

RFC patchgit-grep: correct exit code with --quiet and -L

Subject: [PATCH/RFC] git-grep: correct exit code with --quiet and -L

## tl;dr

5 messages between Aug 15, 2017 and Aug 15, 2017. Diffs are folded; open one to read it.

replies: 4people: 2as markdown or json

Anthony Sottile· Aug 15, 2017, 20:35 UTC · lore

The handling of `status_only` no longer interferes with the handling of `unmatch_name_only`. `--quiet` no longer affects the exit code when using `-L`/`--files-without-match`.

Signed-off-by: Anthony Sottile <asottile@umich.edu>
---
 grep.c          | 9 +++++----
 t/t7810-grep.sh | 5 +++++
 2 files changed, 10 insertions(+), 4 deletions(-)
Show changes to 2 files +10 −4

grep.c, t/t7810-grep.sh

diff --git a/grep.c b/grep.c
index 2efec0e..a893d09 100644
--- a/grep.c
+++ b/grep.c
@@ -1755,7 +1755,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
 		}
 		if (hit) {
 			count++;
-			if (opt->status_only)
+			if (!opt->unmatch_name_only && opt->status_only)
 				return 1;
 			if (opt->name_only) {
 				show_name(opt, gs->name);
@@ -1820,13 +1820,14 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
 	if (collect_hits)
 		return 0;
 
-	if (opt->status_only)
-		return 0;
 	if (opt->unmatch_name_only) {
 		/* We did not see any hit, so we want to show this */
-		show_name(opt, gs->name);
+		if (!opt->status_only)
+			show_name(opt, gs->name);
 		return 1;
 	}
+	if (opt->status_only)
+		return 0;
 
 	xdiff_clear_find_func(&xecfg);
 	opt->priv = NULL;
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index f106387..2a6679c 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -374,6 +374,11 @@ test_expect_success 'grep -L -C' '
 	test_cmp expected actual
 '
 
+test_expect_success 'grep --files-without-match --quiet' '
+	git grep --files-without-match --quiet nonexistent_string >actual &&
+	test_cmp /dev/null actual
+'
+
 cat >expected <<EOF
 file:foo mmap bar_mmap
 EOF
-- 
2.14.GIT
Junio C Hamano· Aug 15, 2017, 21:33 UTC · re: Anthony Sottile · lore

Re: [PATCH/RFC] git-grep: correct exit code with --quiet and -L

Anthony Sottile <asottile@umich.edu> writes:
> The handling of `status_only` no longer interferes with the handling of
> `unmatch_name_only`.  `--quiet` no longer affects the exit code when using
> `-L`/`--files-without-match`.

I agree with the above statement of yours that --quiet should not affect what the exit status is.

But I am not sure what the exit code from these commands _should_ be:

    $ git grep -L qfwfq \*.h    ;# no file matches
    $ git grep -L \# \*.h       ;# some but not all files match
    $ git grep -L . \*.h        ;# all files match

with or without --quiet. I seem to get 0, 0, 1, which I am not sure is correct. I do recall writing "git grep" _without_ thinking what the exit code should be when we added --files-without-match, so the exit status the current code gives out may be just a random garbage.

Asking GNU grep (because --files-without-match is not a POSIX thing):
    $ grep -L qfwfq *.h          ;# no file matches
    $ grep -L \# *.h             ;# some but not all files match
    $ grep -L . *.h              ;# all files match

I seem to get 1, 0, 0. So the exit status should reflect if there was _any_ hit from any file that were inspected.

Show 9 quoted lines
> @@ -1755,7 +1755,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
>  		}
>  		if (hit) {
>  			count++;
> -			if (opt->status_only)
> +			if (!opt->unmatch_name_only && opt->status_only)
>  				return 1;
>  			if (opt->name_only) {
>  				show_name(opt, gs->name);
Does the change in this hunk have any effect?
Just before this hunk there is this code:
		/* "grep -v -e foo -e bla" should list lines
		 * that do not have either, so inversion should
		 * be done outside.
		 */
		if (opt->invert)
			hit = !hit;
		if (opt->unmatch_name_only) {
			if (hit)
				return 0;
			goto next_line;

If (opt->unmatch_name_only && hit) then the function would have already returned and the control wouldn't have reached here.

Which would mean that when the control reaches the line this hunk touches, either one of these must be false, and because we are inside "if (hit)", opt->unmatch_name_only must be false.

Show 15 quoted lines
> @@ -1820,13 +1820,14 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
>  	if (collect_hits)
>  		return 0;
>  
> -	if (opt->status_only)
> -		return 0;
>  	if (opt->unmatch_name_only) {
>  		/* We did not see any hit, so we want to show this */
> -		show_name(opt, gs->name);
> +		if (!opt->status_only)
> +			show_name(opt, gs->name);
>  		return 1;
>  	}
> +	if (opt->status_only)
> +		return 0;

This hunk makes sense to me (provided if the semantics we want out of --files-without-match is sensible, which is dubious), even though I would have limited the change to just a single line, i.e.

	if (opt->status_only)
-		return 0;
+		return opt->unmatch_name_only;
	if (opt->unmatch_name_only) {
		/* We did not see any hit, ... */

But I suspect we want to fix the exit code not to be affected by the "--files-without-match" option in the first place, so all the code changes we see in this patch might be moot X-<.

Anthony Sottile· Aug 15, 2017, 21:41 UTC · re: Junio C Hamano · lore

Re: [PATCH/RFC] git-grep: correct exit code with --quiet and -L

Ah yes, I didn't intend to include the first hunk (forgot to amend it out when formatting the patch).

I think git's exit codes for -L actually make more sense than the GNU exit codes (especially when comparing with `grep` vs `grep -v`) -- that is, produce `0` when the search is successful (producing *something* on stdout) and `1` when the search fails.

Shall I create a new mail with the adjusted patch as suggested above? (I'm not familiar with the expected workflow).

Anthony
On Tue, Aug 15, 2017 at 2:33 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 93 quoted lines
> Anthony Sottile <asottile@umich.edu> writes:
>
>> The handling of `status_only` no longer interferes with the handling of
>> `unmatch_name_only`.  `--quiet` no longer affects the exit code when using
>> `-L`/`--files-without-match`.
>
> I agree with the above statement of yours that --quiet should not
> affect what the exit status is.
>
> But I am not sure what the exit code from these commands _should_
> be:
>
>     $ git grep -L qfwfq \*.h    ;# no file matches
>     $ git grep -L \# \*.h       ;# some but not all files match
>     $ git grep -L . \*.h        ;# all files match
>
> with or without --quiet.  I seem to get 0, 0, 1, which I am not sure
> is correct.  I do recall writing "git grep" _without_ thinking what
> the exit code should be when we added --files-without-match, so the
> exit status the current code gives out may be just a random garbage.
>
> Asking GNU grep (because --files-without-match is not a POSIX thing):
>
>     $ grep -L qfwfq *.h          ;# no file matches
>     $ grep -L \# *.h             ;# some but not all files match
>     $ grep -L . *.h              ;# all files match
>
> I seem to get 1, 0, 0.  So the exit status should reflect if there
> was _any_ hit from any file that were inspected.
>
>> @@ -1755,7 +1755,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
>>               }
>>               if (hit) {
>>                       count++;
>> -                     if (opt->status_only)
>> +                     if (!opt->unmatch_name_only && opt->status_only)
>>                               return 1;
>>                       if (opt->name_only) {
>>                               show_name(opt, gs->name);
>
> Does the change in this hunk have any effect?
>
> Just before this hunk there is this code:
>
>                 /* "grep -v -e foo -e bla" should list lines
>                  * that do not have either, so inversion should
>                  * be done outside.
>                  */
>                 if (opt->invert)
>                         hit = !hit;
>                 if (opt->unmatch_name_only) {
>                         if (hit)
>                                 return 0;
>                         goto next_line;
>
> If (opt->unmatch_name_only && hit) then the function would have
> already returned and the control wouldn't have reached here.
>
> Which would mean that when the control reaches the line this hunk
> touches, either one of these must be false, and because we are
> inside "if (hit)", opt->unmatch_name_only must be false.
>
>> @@ -1820,13 +1820,14 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
>>       if (collect_hits)
>>               return 0;
>>
>> -     if (opt->status_only)
>> -             return 0;
>>       if (opt->unmatch_name_only) {
>>               /* We did not see any hit, so we want to show this */
>> -             show_name(opt, gs->name);
>> +             if (!opt->status_only)
>> +                     show_name(opt, gs->name);
>>               return 1;
>>       }
>> +     if (opt->status_only)
>> +             return 0;
>
> This hunk makes sense to me (provided if the semantics we want out
> of --files-without-match is sensible, which is dubious), even though
> I would have limited the change to just a single line, i.e.
>
>         if (opt->status_only)
> -               return 0;
> +               return opt->unmatch_name_only;
>         if (opt->unmatch_name_only) {
>                 /* We did not see any hit, ... */
>
> But I suspect we want to fix the exit code not to be affected by
> the "--files-without-match" option in the first place, so all the
> code changes we see in this patch might be moot X-<.
>
>
Junio C Hamano· Aug 15, 2017, 22:24 UTC · re: Anthony Sottile · lore

Re: [PATCH/RFC] git-grep: correct exit code with --quiet and -L

Anthony Sottile <asottile@umich.edu> writes:
Show 9 quoted lines
> Ah yes, I didn't intend to include the first hunk (forgot to amend it
> out when formatting the patch).
>
> I think git's exit codes for -L actually make more sense than the GNU
> exit codes (especially when comparing with `grep` vs `grep -v`) --
> that is, produce `0` when the search is successful (producing
> *something* on stdout) and `1` when the search fails.
>
> Shall I create a new mail with the adjusted patch as suggested above?

I do not mind seeing an updated patch that does not change the exit status (as you seem to like what we have currently that contradicts what GNU grep does) but makes it consistent between "--quiet" and "--no-quiet". But I would not be surprised if people seeing this exchange from the sideline are already working on fixing the exit status and also making sure that the fixed code would produce the same corrected exit status with or without "--quiet", so an updated patch from you will likely conflict with their effort.

So if I were you, I'd wait to see what other people would say about the actual exit codes we give when "git grep -L" is run without the "--quiet" option, and if they are also happy with the current exit code, then send in an updated patch.

Thanks.
Anthony Sottile· Aug 15, 2017, 22:43 UTC · re: Junio C Hamano · lore

Re: [PATCH/RFC] git-grep: correct exit code with --quiet and -L

Sounds good, I'll wait.

I've also created a mailing list entry on the gnu grep mailing list as I believe the current exit status for --files-without-match is inconsistent:

http://lists.gnu.org/archive/html/bug-grep/2017-08/msg00010.html
Anthony
On Tue, Aug 15, 2017 at 3:24 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 29 quoted lines
> Anthony Sottile <asottile@umich.edu> writes:
>
>> Ah yes, I didn't intend to include the first hunk (forgot to amend it
>> out when formatting the patch).
>>
>> I think git's exit codes for -L actually make more sense than the GNU
>> exit codes (especially when comparing with `grep` vs `grep -v`) --
>> that is, produce `0` when the search is successful (producing
>> *something* on stdout) and `1` when the search fails.
>>
>> Shall I create a new mail with the adjusted patch as suggested above?
>
> I do not mind seeing an updated patch that does not change the exit
> status (as you seem to like what we have currently that contradicts
> what GNU grep does) but makes it consistent between "--quiet" and
> "--no-quiet".  But I would not be surprised if people seeing this
> exchange from the sideline are already working on fixing the exit
> status and also making sure that the fixed code would produce the
> same corrected exit status with or without "--quiet", so an updated
> patch from you will likely conflict with their effort.
>
> So if I were you, I'd wait to see what other people would say about
> the actual exit codes we give when "git grep -L" is run without the
> "--quiet" option, and if they are also happy with the current exit
> code, then send in an updated patch.
>
> Thanks.
>
>

← back to recent threads