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

Re: [PATCH] grep --no-index: allow use of "git grep" outside a git repository

From
Junio C Hamano <gitster@pobox.com>
Date
Jan 18, 2010, 04:02 UTC
Message-ID
<7v3a24ukku.fsf@alter.siamese.dyndns.org>
In-Reply-To
<7v8wbwultw.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
Show 10 quoted lines
> Jeff King <peff@peff.net> writes:
>
>> Agreed. That is the most common log grep pattern for me (author + grep),
>> and I always want all-match. I see from later in the thread, though,
>> that implementing it is not as straightforward as we might hope.
>
> I haven't looked at the codepath for quite some time but I have a feeling
> that it probably won't be too bad.
>
> It just won't be as simple as flipping the all_match bit with a one-liner.
Perhaps something like this.
-- >8 --
Subject: "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 --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. When parsing the above, behave as if it was specified like this on the command line:

	--all-match --author=me '(' --grep=this --grep=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.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-grep.c |    1 +
 grep.c         |   20 ++++++++++++++++++--
 grep.h         |    2 ++
 revision.c     |    1 +
 4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/builtin-grep.c b/builtin-grep.c
index 529461f..d57c4d9 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -820,6 +820,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	opt.relative = 1;
 	opt.pathname = 1;
 	opt.pattern_tail = &opt.pattern_list;
+	opt.header_tail = &opt.header_list;
 	opt.regflags = REG_NEWLINE;
 	opt.max_depth = -1;
 
diff --git a/grep.c b/grep.c
index bdadf2c..f51fa4a 100644
--- a/grep.c
+++ b/grep.c
@@ -11,8 +11,8 @@ void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field fie
 	p->no = 0;
 	p->token = GREP_PATTERN_HEAD;
 	p->field = field;
-	*opt->pattern_tail = p;
-	opt->pattern_tail = &p->next;
+	*opt->header_tail = p;
+	opt->header_tail = &p->next;
 	p->next = NULL;
 }
 
@@ -173,6 +173,22 @@ void compile_grep_patterns(struct grep_opt *opt)
 {
 	struct grep_pat *p;
 
+	if (opt->header_list && !opt->all_match) {
+		struct grep_pat *p = opt->pattern_list;
+		opt->pattern_list = opt->header_list;
+		opt->pattern_tail = opt->header_tail;
+		opt->header_list = NULL;
+		opt->header_tail = NULL;
+
+		append_grep_pattern(opt, "(", "internal", 0, GREP_OPEN_PAREN);
+		while (p) {
+			*opt->pattern_tail = p;
+			opt->pattern_tail = &p->next;
+			p = p->next;
+		}
+		append_grep_pattern(opt, ")", "internal", 0, GREP_CLOSE_PAREN);
+		opt->all_match = 1;
+	}
 	if (opt->all_match)
 		opt->extended = 1;
 
diff --git a/grep.h b/grep.h
index 75370f6..e39e514 100644
--- a/grep.h
+++ b/grep.h
@@ -59,6 +59,8 @@ struct grep_expr {
 struct grep_opt {
 	struct grep_pat *pattern_list;
 	struct grep_pat **pattern_tail;
+	struct grep_pat *header_list;
+	struct grep_pat **header_tail;
 	struct grep_expr *pattern_expression;
 	const char *prefix;
 	int prefix_length;
diff --git a/revision.c b/revision.c
index 25fa14d..18a3658 100644
--- a/revision.c
+++ b/revision.c
@@ -806,6 +806,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
 
 	revs->grep_filter.status_only = 1;
 	revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
+	revs->grep_filter.header_tail = &(revs->grep_filter.header_list);
 	revs->grep_filter.regflags = REG_NEWLINE;
 
 	diff_setup(&revs->diffopt);
Previous: Junio C HamanoNext: Jeff King
Message 16 of 20 in “Filenames and prefixes in extended diffs”
  1. Andreas GruenbacherJan 13, 2010
  2. Junio C HamanoJan 13, 2010
  3. Junio C HamanoJan 14, 2010
  4. Nanako ShiraishiJan 15, 2010
  5. Junio C HamanoJan 15, 2010
  6. grep: prepare to run outside of a work treeJunio C Hamano, Jan 15, 2010
  7. grep --no-index: allow use of "git grep" outside a git repositoryJunio C Hamano, Jan 15, 2010
  8. Jeff KingJan 15, 2010
  9. Junio C HamanoJan 16, 2010
  10. Jeff KingJan 16, 2010
  11. Junio C HamanoJan 16, 2010
  12. David AguilarJan 16, 2010
  13. Junio C HamanoJan 16, 2010
  14. Jeff KingJan 18, 2010
  15. Junio C HamanoJan 18, 2010
  16. Junio C HamanoJan 18, 2010
  17. Jeff KingJan 18, 2010
  18. Junio C HamanoJan 18, 2010
  19. Jeff KingJan 18, 2010
  20. Andreas GruenbacherJan 18, 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.