git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git-grep: option parsing conflicts with prefix-dash searches

From
Jeff King <peff@peff.net>
Date
Feb 6, 2010, 03:51 UTC
Message-ID
<20100206035143.GA31784@sigill.intra.peff.net>
In-Reply-To
<7vsk9fs1j9.fsf@alter.siamese.dyndns.org>
On Fri, Feb 05, 2010 at 03:31:06PM -0800, Junio C Hamano wrote:
Show 15 quoted lines
> Jan Engelhardt <jengelh@medozas.de> writes:
> 
> > Just about now I wanted to grep for accesses of a particular struct 
> > member. Needless to say that it was not a very amusing experience.
> > I would expect that (1) probably fails:
> >
> > (1)	$ git grep '->cnt' net/ipv4/netfilter/
> > 	error: unknown switch `>'
> >
> > So far so good, seems reasonable and matches what I would expect from 
> > most other userspace tools. So let's add -- to terminate the option 
> > list:
> 
> Also you can say "grep -e '->cnt'".  Not just "git grep" but regular grep
> understands this, too.

GNU grep understands "grep -- '->cnt'", so I find myself typing it a lot. Even though "--" is used for revision and pathname separation, I don't think there is a conflict in also using it to separate options from patterns for the case that there is no "-e" at all. In other words:

  git grep -- foo

is not ambiguous. That "--" could not possibly be separating revisions from pathnames because we have not yet seen any pattern, which is bogus. In a case like:

  git grep -e pattern -- foo

I think it is clear that the "--" is separating pathnames, because we already have a pathname. This matches standard grep, which will treat the first non-option as a pattern only if we have no "-e" pattern.

So I think we can do just do this:
diff --git a/builtin-grep.c b/builtin-grep.c
index 0ef849c..46ffc1d 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -889,6 +889,16 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		/* die the same way as if we did it at the beginning */
 		setup_git_directory();
 
+	/*
+	 * skip a -- separator; we know it cannot be
+	 * separating revisions from pathnames if
+	 * we haven't even had any patterns yet
+	 */
+	if (argc > 0 && !opt.pattern_list && !strcmp(argv[0], "--")) {
+		argv++;
+		argc--;
+	}
+
 	/* First unrecognized non-option token */
 	if (argc > 0 && !opt.pattern_list) {
 		append_grep_pattern(&opt, argv[0], "command line", 0,

and make everybody happy. But I admit I haven't thought about it more
than 5 minutes or so, so perhaps there is a case I am missing that will
be ambiguous or confusing. The worst I could come up with is the
double-double-dash case:

  git grep -- pattern revision -- pathname

It is perhaps not as pretty as

  git grep -e pattern revision -- pathname

but I don't think it is ambiguous.

> > (2)	$ git grep -- '->cnt' net/ipv4/netfilter/
> > 	fatal: bad flag '->cnt' used after filename
> >
> > *bzzt*.
> 
> This indeed is bzzt, especially if you had a file called "./->cnt" in the
> work tree.  That would mean that you cannot tell the command to look for a
> pattern in the work tree.
> 
> But because you are not giving anything before "--", that "git grep" is
> not looking for anything.  Indeed, (2) is a user error.  If you try this:

That is not quite true. The way "git grep" is implemented now, it is
actually grepping for "--". parse_options stops at the "--", leaving it
in argv, and then we assume whatever is left by parse_options is a
pattern (since we saw no "-e"). But of course it is looking in the
'->cnt' pathspec (or revision!), which is bogus (and gets you "bad flag used
after filename").

But as you noted with:

> > What works is (3).
> >
> > (3)	$ git grep -- -- '->cnt' net/ipv4/netfilter/

...disambiguating the pathspec with the extra "--" gets it past option
parsing and looking for "--".

So actually my patch above is breaking somebody who truly wanted to grep
for "--" by doing

  git grep --

but that is sufficiently insane that I'm not too worried about it.

-Peff
Previous: Junio C HamanoNext: Junio C Hamano
Message 6 of 12 in “git-grep: option parsing conflicts with prefix-dash searches”
  1. Jan EngelhardtFeb 5, 2010
  2. Jan EngelhardtFeb 5, 2010
  3. Santi BéjarFeb 5, 2010
  4. Junio C HamanoFeb 5, 2010
  5. Junio C HamanoFeb 5, 2010
  6. Jeff KingFeb 6, 2010
  7. Junio C HamanoFeb 6, 2010
  8. Miles BaderFeb 6, 2010
  9. Jeff KingFeb 6, 2010
  10. Junio C HamanoFeb 6, 2010
  11. Jeff KingFeb 7, 2010
  12. Junio C HamanoFeb 8, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.