git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages
@ 2012-09-26 12:12 Nguyễn Thái Ngọc Duy
  2012-09-26 14:07 ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-26 12:12 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Both "git log" and "git reflog show" recognize this option.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Itch: how to show reflogs for checkout operation only?

 Instead of ignoring when -g is not given, we might want to imply -g.

 Still itch: grep highlight! For all applicable areas: commit headers
 including reflog messages, commit body, diff.

 Documentation/rev-list-options.txt |  5 +++++
 revision.c                         | 30 ++++++++++++++++++++++++++++++
 revision.h                         |  1 +
 3 files changed, 36 insertions(+)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 1fc2a18..aeaa58c 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -51,6 +51,11 @@ endif::git-rev-list[]
 	commits whose author matches any of the given patterns are
 	chosen (similarly for multiple `--committer=<pattern>`).
 
+--reflog-message=<pattern>::
+	Limit the commits output to ones with reflog messages that
+	match the specified pattern (regular expression). Ignored unless
+	--walk-reflogs is given.
+
 --grep=<pattern>::
 
 	Limit the commits output to ones with log message that
diff --git a/revision.c b/revision.c
index ae12e11..ee55bb2 100644
--- a/revision.c
+++ b/revision.c
@@ -1053,6 +1053,11 @@ void init_revisions(struct rev_info *revs, const char *prefix)
 	revs->grep_filter.header_tail = &(revs->grep_filter.header_list);
 	revs->grep_filter.regflags = REG_NEWLINE;
 
+	revs->reflog_filter.status_only = 1;
+	revs->reflog_filter.pattern_tail = &(revs->reflog_filter.pattern_list);
+	revs->reflog_filter.header_tail = &(revs->reflog_filter.header_list);
+	revs->reflog_filter.regflags = REG_NEWLINE;
+
 	diff_setup(&revs->diffopt);
 	if (prefix && !revs->diffopt.prefix) {
 		revs->diffopt.prefix = prefix;
@@ -1298,6 +1303,12 @@ static void add_message_grep(struct rev_info *revs, const char *pattern)
 	add_grep(revs, pattern, GREP_PATTERN_BODY);
 }
 
+static void add_reflog_grep(struct rev_info *revs, const char *ptn)
+{
+	append_grep_pattern(&revs->reflog_filter, ptn,
+			    "command line", 0, GREP_PATTERN);
+}
+
 static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
 			       int *unkc, const char **unkv)
 {
@@ -1600,15 +1611,23 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		return argcount;
 	} else if (!strcmp(arg, "--grep-debug")) {
 		revs->grep_filter.debug = 1;
+	} else if ((argcount = parse_long_opt("reflog-message",
+					      argv, &optarg))) {
+		add_reflog_grep(revs, optarg);
+		return argcount;
 	} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
 		revs->grep_filter.regflags |= REG_EXTENDED;
+		revs->reflog_filter.regflags |= REG_EXTENDED;
 	} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
 		revs->grep_filter.regflags |= REG_ICASE;
+		revs->reflog_filter.regflags |= REG_ICASE;
 		DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
 	} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
 		revs->grep_filter.fixed = 1;
+		revs->reflog_filter.fixed = 1;
 	} else if (!strcmp(arg, "--all-match")) {
 		revs->grep_filter.all_match = 1;
+		revs->reflog_filter.all_match = 1;
 	} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
 		if (strcmp(optarg, "none"))
 			git_log_output_encoding = xstrdup(optarg);
@@ -1891,6 +1910,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 	diff_setup_done(&revs->diffopt);
 
 	compile_grep_patterns(&revs->grep_filter);
+	compile_grep_patterns(&revs->reflog_filter);
 
 	if (revs->reverse && revs->reflog_info)
 		die("cannot combine --reverse with --walk-reflogs");
@@ -2242,6 +2262,16 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
 		    ((revs->max_parents >= 0) && (n > revs->max_parents)))
 			return commit_ignore;
 	}
+	if (revs->reflog_info &&
+	    revs->reflog_filter.pattern_list) {
+		struct strbuf sb = STRBUF_INIT;
+		int ignore;
+		get_reflog_message(&sb, revs->reflog_info);
+		ignore = !grep_buffer(&revs->reflog_filter, sb.buf, sb.len);
+		strbuf_release(&sb);
+		if (ignore)
+			return commit_ignore;
+	}
 	if (!commit_match(commit, revs))
 		return commit_ignore;
 	if (revs->prune && revs->dense) {
diff --git a/revision.h b/revision.h
index a95bd0b..0ebe34b 100644
--- a/revision.h
+++ b/revision.h
@@ -145,6 +145,7 @@ struct rev_info {
 
 	/* Filter by commit log message */
 	struct grep_opt	grep_filter;
+	struct grep_opt	reflog_filter;
 
 	/* Display history graph */
 	struct git_graph *graph;
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages
  2012-09-26 12:12 [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages Nguyễn Thái Ngọc Duy
@ 2012-09-26 14:07 ` Junio C Hamano
  2012-09-26 14:15   ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2012-09-26 14:07 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> Both "git log" and "git reflog show" recognize this option.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---

How well does it interact with --grep and/or --all-match?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages
  2012-09-26 14:07 ` Junio C Hamano
@ 2012-09-26 14:15   ` Nguyen Thai Ngoc Duy
  2012-09-26 19:28     ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-09-26 14:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Wed, Sep 26, 2012 at 9:07 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>
>> Both "git log" and "git reflog show" recognize this option.
>>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>> ---
>
> How well does it interact with --grep and/or --all-match?

Good point. It currently works like and operator. But people might
expect to combine them in different ways.
-- 
Duy

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages
  2012-09-26 14:15   ` Nguyen Thai Ngoc Duy
@ 2012-09-26 19:28     ` Junio C Hamano
  2012-09-27 11:36       ` [PATCH] revision: add --reflog-message " Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2012-09-26 19:28 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: git

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

> On Wed, Sep 26, 2012 at 9:07 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>>
>>> Both "git log" and "git reflog show" recognize this option.
>>>
>>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>>> ---
>>
>> How well does it interact with --grep and/or --all-match?
>
> Good point. It currently works like and operator. But people might
> expect to combine them in different ways.

The current commit_match() runs grep_buffer() on commit->buffer.  It
probably makes sense to instead notice from opt that we are running
log with "-g", prepare a temporary strbuf and add in the reflog
message to the string in commit->buffer, and run grep_buffer() on
that temporary strbuf on it.

I personally think it is sufficient ot just reuse --grep on
concatenation of commit->buffer with "Reflog message: checkout:
moving from as/check-ignore to pu".

If you really want to go fancier, you could add --grep-reflog option
that behaves like the existing --author and --committer options to
add "header match" elements to the grep expression, splice a fake
"reflog " header to the string copied from commit->buffer, e.g.
prepare something like this in your temporary strbuf:

    tree b4429f218782165faf101ccb0f4ba1cdd6d1d349
    parent de5cd03876e546d6d264ab28a01daa978f3eae78
    parent b378e5a25658e07e6d0c0f4db79e87cb21de5489
    author Junio C Hamano <gitster@pobox.com> 1348616180 -0700
    committer Junio C Hamano <gitster@pobox.com> 1348616180 -0700
    reflog checkout: moving from as/check-ignore to pu

    Merge branch 'jk/lua-hackery' into pu

    * jk/lua-hackery:
      Minimum compilation fixup
      Makefile: make "lua" a bit more configurable
      add a "lua" pretty format
      add basic lua infrastructure
      pretty: make some commit-parsing helpers more public

that way, you can take advantage of the existing logic used for the
author/committer match that matches only in the commit object
header.

Again, I personally doubt the fancier option is worth it, but the
starting point may look something like this.

 revision.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git c/revision.c w/revision.c
index ae12e11..b0f4d5b 100644
--- c/revision.c
+++ w/revision.c
@@ -2212,8 +2212,20 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 {
 	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
 		return 1;
-	return grep_buffer(&opt->grep_filter,
-			   commit->buffer, strlen(commit->buffer));
+
+	if (opt->reflog_info) {
+		int retval;
+		struct strbuf buf = STRBUF_INIT;
+		strbuf_addf(&buf, "reflog %s\n", opt->reflog_info->message);
+		strbuf_addstr(&buf, commit->buffer);
+		retval = grep_buffer(&opt->grep_filter,
+				     buf.buf, buf.len);
+		strbuf_release(&buf);
+		return retval;
+	} else {
+		return grep_buffer(&opt->grep_filter,
+				   commit->buffer, strlen(commit->buffer));
+	}
 }
 
 static inline int want_ancestry(struct rev_info *revs)

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH] revision: add --reflog-message to grep reflog messages
  2012-09-26 19:28     ` Junio C Hamano
@ 2012-09-27 11:36       ` Nguyễn Thái Ngọc Duy
  2012-09-27 17:09         ` Junio C Hamano
  2012-09-28  7:01         ` [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers Nguyễn Thái Ngọc Duy
  0 siblings, 2 replies; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-27 11:36 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Thu, Sep 27, 2012 at 2:28 AM, Junio C Hamano <gitster@pobox.com> wrote:
 > The current commit_match() runs grep_buffer() on commit->buffer.  It
 > probably makes sense to instead notice from opt that we are running
 > log with "-g", prepare a temporary strbuf and add in the reflog
 > message to the string in commit->buffer, and run grep_buffer() on
 > that temporary strbuf on it.

 Yeah. I was starting to think that way too, otherwise combining grep
 options would be a mess. I was hoping by injecting a fake reflog
 header, we could simplify reflog exceptions in pretty.c. But it
 was not that easy.

 > I personally think it is sufficient ot just reuse --grep on
 > concatenation of commit->buffer with "Reflog message: checkout:
 > moving from as/check-ignore to pu".

 --grep only reads the commit body. So either we append reflog
 message to commit body, or we put it in the header and add a new
 option for it. I don't like appending things to the commit body as
 --grep may hit reflog message while users do not mean so.

 > If you really want to go fancier, you could add --grep-reflog option
 > that behaves like the existing --author and --committer options to
 > add "header match" elements to the grep expression, splice a fake
 > "reflog " header to the string copied from commit->buffer

 Inserting at the beginning of the commit like your demo patch works
 just fine and is simpler. I'm tempted to take the undocumented option
 name --reflog for this purpose. But it's probably not worth the risk.

 Documentation/rev-list-options.txt |  5 +++++
 grep.c                             |  1 +
 grep.h                             |  5 +++--
 revision.c                         | 19 +++++++++++++++++--
 t/t7810-grep.sh                    |  6 ++++++
 5 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 1fc2a18..aeaa58c 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -51,6 +51,11 @@ endif::git-rev-list[]
 	commits whose author matches any of the given patterns are
 	chosen (similarly for multiple `--committer=<pattern>`).
 
+--reflog-message=<pattern>::
+	Limit the commits output to ones with reflog entries that
+	match the specified pattern (regular expression). Ignored unless
+	--walk-reflogs is given.
+
 --grep=<pattern>::
 
 	Limit the commits output to ones with log message that
diff --git a/grep.c b/grep.c
index 898be6e..72ac1bf 100644
--- a/grep.c
+++ b/grep.c
@@ -697,6 +697,7 @@ static struct {
 } header_field[] = {
 	{ "author ", 7 },
 	{ "committer ", 10 },
+	{ "reflog ", 7 },
 };
 
 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
diff --git a/grep.h b/grep.h
index 8a28a67..1416ad7 100644
--- a/grep.h
+++ b/grep.h
@@ -29,9 +29,10 @@ enum grep_context {
 
 enum grep_header_field {
 	GREP_HEADER_AUTHOR = 0,
-	GREP_HEADER_COMMITTER
+	GREP_HEADER_COMMITTER,
+	GREP_HEADER_REFLOG,
+	GREP_HEADER_FIELD_MAX
 };
-#define GREP_HEADER_FIELD_MAX (GREP_HEADER_COMMITTER + 1)
 
 struct grep_pat {
 	struct grep_pat *next;
diff --git a/revision.c b/revision.c
index ae12e11..837051c 100644
--- a/revision.c
+++ b/revision.c
@@ -1595,6 +1595,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
 		add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
 		return argcount;
+	} else if ((argcount = parse_long_opt("reflog-message", argv, &optarg))) {
+		add_header_grep(revs, GREP_HEADER_REFLOG, optarg);
+		return argcount;
 	} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
 		add_message_grep(revs, optarg);
 		return argcount;
@@ -2212,8 +2215,20 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 {
 	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
 		return 1;
-	return grep_buffer(&opt->grep_filter,
-			   commit->buffer, strlen(commit->buffer));
+	if (opt->reflog_info) {
+		int retval;
+		struct strbuf buf = STRBUF_INIT;
+		strbuf_addstr(&buf, "reflog ");
+		get_reflog_message(&buf, opt->reflog_info);
+		strbuf_addch(&buf, '\n');
+		strbuf_addstr(&buf, commit->buffer);
+		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
+		strbuf_release(&buf);
+		return retval;
+	} else {
+		return grep_buffer(&opt->grep_filter,
+				   commit->buffer, strlen(commit->buffer));
+	}
 }
 
 static inline int want_ancestry(struct rev_info *revs)
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 91db352..a0f519e 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -546,6 +546,12 @@ test_expect_success 'log grep (6)' '
 	test_cmp expect actual
 '
 
+test_expect_success 'log grep (7)' '
+	git log -g --reflog-message="commit: third" --pretty=tformat:%s >actual &&
+	echo third >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'log with multiple --grep uses union' '
 	git log --grep=i --grep=r --format=%s >actual &&
 	{
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message to grep reflog messages
  2012-09-27 11:36       ` [PATCH] revision: add --reflog-message " Nguyễn Thái Ngọc Duy
@ 2012-09-27 17:09         ` Junio C Hamano
  2012-09-27 17:28           ` Jeff King
  2012-09-28  7:01         ` [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers Nguyễn Thái Ngọc Duy
  1 sibling, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2012-09-27 17:09 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:

> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---

Plase explain yourself in the space above.

> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
> index 1fc2a18..aeaa58c 100644
> --- a/Documentation/rev-list-options.txt
> +++ b/Documentation/rev-list-options.txt
> @@ -51,6 +51,11 @@ endif::git-rev-list[]
>  	commits whose author matches any of the given patterns are
>  	chosen (similarly for multiple `--committer=<pattern>`).
>  
> +--reflog-message=<pattern>::
> +	Limit the commits output to ones with reflog entries that
> +	match the specified pattern (regular expression). Ignored unless
> +	--walk-reflogs is given.
> +

I am debating myself if it is sane for this option to have no hint
that it is about "limiting" in its name.  "--author/--committer"
don't and it is clear from the context of the command that they are
not about setting author/committer, so "--reflog-message" may be
interpreted the same, perhaps.

The entry in the context above talks about multiple occurrence of
that option. Shouldn't this new one also say what happens when it is
given twice?

> diff --git a/grep.c b/grep.c
> index 898be6e..72ac1bf 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -697,6 +697,7 @@ static struct {
>  } header_field[] = {
>  	{ "author ", 7 },
>  	{ "committer ", 10 },
> +	{ "reflog ", 7 },
>  };
>  
>  static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
> diff --git a/grep.h b/grep.h
> index 8a28a67..1416ad7 100644
> --- a/grep.h
> +++ b/grep.h
> @@ -29,9 +29,10 @@ enum grep_context {
>  
>  enum grep_header_field {
>  	GREP_HEADER_AUTHOR = 0,
> -	GREP_HEADER_COMMITTER
> +	GREP_HEADER_COMMITTER,
> +	GREP_HEADER_REFLOG,
> +	GREP_HEADER_FIELD_MAX
>  };
> -#define GREP_HEADER_FIELD_MAX (GREP_HEADER_COMMITTER + 1)

Please add comment to ensure that FIELD_MAX stays at the end; if you
ensure that, the result is much better than the original "we know
committer is at the end so add one".

I think I wrote prep_header_patterns() and compile_grep_patterns()
carefully enough not to assume the headers are only the author and
committer names, so the various combinations i.e. all-match,
author(s), committer(s), grep(s), and reflog-message(s), should work
out of the box, but have you actually tested them?

I do not know offhand the matching side is prepared to take random
garbage fields.  IIRC, we strip the trailing timestamp from committer
and author header lines when we match, and a new code needs to be
added to control when that stripping should / should not kick in
depending on the header.

> diff --git a/revision.c b/revision.c
> index ae12e11..837051c 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -1595,6 +1595,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
>  	} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
>  		add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
>  		return argcount;
> +	} else if ((argcount = parse_long_opt("reflog-message", argv, &optarg))) {
> +		add_header_grep(revs, GREP_HEADER_REFLOG, optarg);
> +		return argcount;
>  	} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
>  		add_message_grep(revs, optarg);
>  		return argcount;
> @@ -2212,8 +2215,20 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
>  {
>  	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
>  		return 1;
> -	return grep_buffer(&opt->grep_filter,
> -			   commit->buffer, strlen(commit->buffer));
> +	if (opt->reflog_info) {
> +		int retval;
> +		struct strbuf buf = STRBUF_INIT;
> +		strbuf_addstr(&buf, "reflog ");
> +		get_reflog_message(&buf, opt->reflog_info);
> +		strbuf_addch(&buf, '\n');
> +		strbuf_addstr(&buf, commit->buffer);
> +		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
> +		strbuf_release(&buf);
> +		return retval;
> +	} else {
> +		return grep_buffer(&opt->grep_filter,
> +				   commit->buffer, strlen(commit->buffer));
> +	}
>  }

This part looks familiar and smells sane ;-)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message to grep reflog messages
  2012-09-27 17:09         ` Junio C Hamano
@ 2012-09-27 17:28           ` Jeff King
  2012-09-27 18:16             ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Jeff King @ 2012-09-27 17:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy, git

On Thu, Sep 27, 2012 at 10:09:28AM -0700, Junio C Hamano wrote:

> > +--reflog-message=<pattern>::
> > +	Limit the commits output to ones with reflog entries that
> > +	match the specified pattern (regular expression). Ignored unless
> > +	--walk-reflogs is given.
> > +
> 
> I am debating myself if it is sane for this option to have no hint
> that it is about "limiting" in its name.  "--author/--committer"
> don't and it is clear from the context of the command that they are
> not about setting author/committer, so "--reflog-message" may be
> interpreted the same, perhaps.

I also found the name confusing on first-read. While "--author" is an
example in one direction, the fact that "--grep" is not called "--body"
is a counter-example.

I'd much rather see it as "--grep-reflog" or something. You could also
do "--grep-reflog-message", which would match a later
"--grep-reflog-author", but I am not sure anybody would want the latter,
and it makes the current name a lot longer.

I actually think just checking the reflog when we call "--grep" would
the most common workflow, and requires no extra work from the user.  My
only hesitation is that if somebody _does_ want to distinguish, there's
no escape hatch. Of course, the reflog walker is already full of such
weird conflations (e.g., the rewriting of parent and date information).

-Peff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] revision: add --reflog-message to grep reflog messages
  2012-09-27 17:28           ` Jeff King
@ 2012-09-27 18:16             ` Junio C Hamano
  0 siblings, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2012-09-27 18:16 UTC (permalink / raw)
  To: Jeff King; +Cc: Nguyễn Thái Ngọc Duy, git

Jeff King <peff@peff.net> writes:

> I actually think just checking the reflog when we call "--grep" would
> the most common workflow, and requires no extra work from the user.  My
> only hesitation is that if somebody _does_ want to distinguish, there's
> no escape hatch. Of course, the reflog walker is already full of such
> weird conflations (e.g., the rewriting of parent and date information).

Yes, that reasoning more-or-less matches the reason why I said we do
not necessarily want to go "fancier".  But "log -g" output already
makes it fairly clear that the additional information is not part of
the regular log and is a some header-like thingy, so I actually am
OK with --reflog-grep and --grep being different.

The output from "log --show-notes", on the other hand, is even more
conflated and a casual user would view it as part of the message, so
I would imagine that if we ever do the extention to cover notes
data, the normal "--grep" should apply to it.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers
  2012-09-27 11:36       ` [PATCH] revision: add --reflog-message " Nguyễn Thái Ngọc Duy
  2012-09-27 17:09         ` Junio C Hamano
@ 2012-09-28  7:01         ` Nguyễn Thái Ngọc Duy
  2012-09-28  7:01           ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
  2012-09-28  7:01           ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
  1 sibling, 2 replies; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-28  7:01 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Fri, Sep 28, 2012 at 12:09 AM, Junio C Hamano <gitster@pobox.com> wrote:
 >>  enum grep_header_field {
 >>       GREP_HEADER_AUTHOR = 0,
 >> -     GREP_HEADER_COMMITTER
 >> +     GREP_HEADER_COMMITTER,
 >> +     GREP_HEADER_REFLOG,
 >> +     GREP_HEADER_FIELD_MAX
 >>  };
 >> -#define GREP_HEADER_FIELD_MAX (GREP_HEADER_COMMITTER + 1)
 >
 > Please add comment to ensure that FIELD_MAX stays at the end; if you
 > ensure that, the result is much better than the original "we know
 > committer is at the end so add one".

 It's probably even better to remove the enum. Say one day I got drunk
 and decided to add --grep-encoding. This patch makes sure that I could
 submit such a patch even in drunk state.

 grep.c     | 76 +++++++++++++++++++++++++++++++++-----------------------------
 grep.h     | 11 +++------
 revision.c |  8 +++----
 3 files changed, 47 insertions(+), 48 deletions(-)

diff --git a/grep.c b/grep.c
index 898be6e..0c72262 100644
--- a/grep.c
+++ b/grep.c
@@ -10,7 +10,7 @@ static int grep_source_is_binary(struct grep_source *gs);
 static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
 					const char *origin, int no,
 					enum grep_pat_token t,
-					enum grep_header_field field)
+					const char *header, size_t header_len)
 {
 	struct grep_pat *p = xcalloc(1, sizeof(*p));
 	p->pattern = xmemdupz(pat, patlen);
@@ -18,7 +18,8 @@ static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
 	p->origin = origin;
 	p->no = no;
 	p->token = t;
-	p->field = field;
+	p->header = header;
+	p->header_len = header_len;
 	return p;
 }
 
@@ -45,7 +46,8 @@ static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
 			if (!nl)
 				break;
 			new_pat = create_grep_pat(nl + 1, len - 1, p->origin,
-						  p->no, p->token, p->field);
+						  p->no, p->token,
+						  p->header, p->header_len);
 			new_pat->next = p->next;
 			if (!p->next)
 				*tail = &new_pat->next;
@@ -59,11 +61,13 @@ static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
 	}
 }
 
+/* header must not be freed while grep is running */
 void append_header_grep_pattern(struct grep_opt *opt,
-				enum grep_header_field field, const char *pat)
+				const char *header, const char *pat)
 {
 	struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
-					     GREP_PATTERN_HEAD, field);
+					     GREP_PATTERN_HEAD,
+					     header, strlen(header));
 	do_append_grep_pat(&opt->header_tail, p);
 }
 
@@ -76,7 +80,7 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
 void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
 		     const char *origin, int no, enum grep_pat_token t)
 {
-	struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, 0);
+	struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, NULL, 0);
 	do_append_grep_pat(&opt->pattern_tail, p);
 }
 
@@ -92,7 +96,7 @@ struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
 	for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
 	{
 		if(pat->token == GREP_PATTERN_HEAD)
-			append_header_grep_pattern(ret, pat->field,
+			append_header_grep_pattern(ret, pat->header,
 						   pat->pattern);
 		else
 			append_grep_pat(ret, pat->pattern, pat->patternlen,
@@ -359,7 +363,7 @@ static void dump_grep_pat(struct grep_pat *p)
 	switch (p->token) {
 	default: break;
 	case GREP_PATTERN_HEAD:
-		fprintf(stderr, "<head %d>", p->field); break;
+		fprintf(stderr, "<head %s>", p->header); break;
 	case GREP_PATTERN_BODY:
 		fprintf(stderr, "<body>"); break;
 	}
@@ -436,9 +440,10 @@ static struct grep_expr *grep_or_expr(struct grep_expr *left, struct grep_expr *
 static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
 {
 	struct grep_pat *p;
-	struct grep_expr *header_expr;
-	struct grep_expr *(header_group[GREP_HEADER_FIELD_MAX]);
-	enum grep_header_field fld;
+	struct grep_expr *header_expr = NULL;
+	struct grep_expr **header_group;
+	struct string_list header = STRING_LIST_INIT_NODUP;
+	int fld;
 
 	if (!opt->header_list)
 		return NULL;
@@ -446,37 +451,45 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
 	for (p = opt->header_list; p; p = p->next) {
 		if (p->token != GREP_PATTERN_HEAD)
 			die("bug: a non-header pattern in grep header list.");
-		if (p->field < 0 || GREP_HEADER_FIELD_MAX <= p->field)
-			die("bug: unknown header field %d", p->field);
+		if (!p->header || !p->header_len)
+			die("bug: unknown header field");
 		compile_regexp(p, opt);
+		string_list_append(&header, p->header);
 	}
 
-	for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++)
-		header_group[fld] = NULL;
+	sort_string_list(&header);
+	string_list_remove_duplicates(&header, 0);
+	header_group = xmalloc(sizeof(*header_group) * header.nr);
+	memset(header_group, 0, sizeof(*header_group) * header.nr);
 
 	for (p = opt->header_list; p; p = p->next) {
 		struct grep_expr *h;
 		struct grep_pat *pp = p;
+		struct string_list_item *item;
 
 		h = compile_pattern_atom(&pp);
 		if (!h || pp != p->next)
 			die("bug: malformed header expr");
-		if (!header_group[p->field]) {
-			header_group[p->field] = h;
+		item = string_list_lookup(&header, p->header);
+		if (!item)
+			die("bug: malformed header expr");
+		fld = item - header.items;
+		if (!header_group[fld]) {
+			header_group[fld] = h;
 			continue;
 		}
-		header_group[p->field] = grep_or_expr(h, header_group[p->field]);
+		header_group[fld] = grep_or_expr(h, header_group[fld]);
 	}
 
-	header_expr = NULL;
-
-	for (fld = 0; fld < GREP_HEADER_FIELD_MAX; fld++) {
-		if (!header_group[fld])
-			continue;
+	for (fld = 0; fld < header.nr; fld++) {
 		if (!header_expr)
 			header_expr = grep_true_expr();
 		header_expr = grep_or_expr(header_group[fld], header_expr);
 	}
+
+	string_list_clear(&header, 0);
+	free(header_group);
+
 	return header_expr;
 }
 
@@ -691,14 +704,6 @@ static int strip_timestamp(char *bol, char **eol_p)
 	return 0;
 }
 
-static struct {
-	const char *field;
-	size_t len;
-} header_field[] = {
-	{ "author ", 7 },
-	{ "committer ", 10 },
-};
-
 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 			     enum grep_context ctx,
 			     regmatch_t *pmatch, int eflags)
@@ -714,12 +719,11 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 	if (p->token == GREP_PATTERN_HEAD) {
 		const char *field;
 		size_t len;
-		assert(p->field < ARRAY_SIZE(header_field));
-		field = header_field[p->field].field;
-		len = header_field[p->field].len;
-		if (strncmp(bol, field, len))
+		field = p->header;
+		len = p->header_len;
+		if (strncmp(bol, field, len) || bol[len] != ' ')
 			return 0;
-		bol += len;
+		bol += len + 1;
 		saved_ch = strip_timestamp(bol, &eol);
 	}
 
diff --git a/grep.h b/grep.h
index 8a28a67..bc00f2a 100644
--- a/grep.h
+++ b/grep.h
@@ -27,12 +27,6 @@ enum grep_context {
 	GREP_CONTEXT_BODY
 };
 
-enum grep_header_field {
-	GREP_HEADER_AUTHOR = 0,
-	GREP_HEADER_COMMITTER
-};
-#define GREP_HEADER_FIELD_MAX (GREP_HEADER_COMMITTER + 1)
-
 struct grep_pat {
 	struct grep_pat *next;
 	const char *origin;
@@ -40,7 +34,8 @@ struct grep_pat {
 	enum grep_pat_token token;
 	char *pattern;
 	size_t patternlen;
-	enum grep_header_field field;
+	const char *header;
+	size_t header_len;
 	regex_t regexp;
 	pcre *pcre_regexp;
 	pcre_extra *pcre_extra_info;
@@ -136,7 +131,7 @@ struct grep_opt {
 
 extern void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
 extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
-extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
+extern void append_header_grep_pattern(struct grep_opt *, const char *, const char *);
 extern void compile_grep_patterns(struct grep_opt *opt);
 extern void free_grep_patterns(struct grep_opt *opt);
 extern int grep_buffer(struct grep_opt *opt, char *buf, unsigned long size);
diff --git a/revision.c b/revision.c
index ae12e11..f7cf385 100644
--- a/revision.c
+++ b/revision.c
@@ -1288,9 +1288,9 @@ static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token
 	append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
 }
 
-static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
+static void add_header_grep(struct rev_info *revs, const char *header, const char *pattern)
 {
-	append_header_grep_pattern(&revs->grep_filter, field, pattern);
+	append_header_grep_pattern(&revs->grep_filter, header, pattern);
 }
 
 static void add_message_grep(struct rev_info *revs, const char *pattern)
@@ -1590,10 +1590,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	 * Grepping the commit log
 	 */
 	else if ((argcount = parse_long_opt("author", argv, &optarg))) {
-		add_header_grep(revs, GREP_HEADER_AUTHOR, optarg);
+		add_header_grep(revs, "author", optarg);
 		return argcount;
 	} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
-		add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
+		add_header_grep(revs, "committer", optarg);
 		return argcount;
 	} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
 		add_message_grep(revs, optarg);
-- 
1.7.12.1.405.gb727dc9

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-28  7:01         ` [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers Nguyễn Thái Ngọc Duy
@ 2012-09-28  7:01           ` Nguyễn Thái Ngọc Duy
  2012-09-28 17:55             ` Junio C Hamano
  2012-09-28  7:01           ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
  1 sibling, 1 reply; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-28  7:01 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

Similar to --author/--committer which filters commits by author and
committer header fields. --grep-reflog adds a fake "reflog" header to
commit and a grep filter to search on that line.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Fri, Sep 28, 2012 at 12:09 AM, Junio C Hamano <gitster@pobox.com>
 wrote:
 > I am debating myself if it is sane for this option to have no hint
 > that it is about "limiting" in its name.  "--author/--committer"
 > don't and it is clear from the context of the command that they are
 > not about setting author/committer, so "--reflog-message" may be
 > interpreted the same, perhaps.
 >
 > The entry in the context above talks about multiple occurrence of
 > that option. Shouldn't this new one also say what happens when it
 > is
 > given twice?

 Fixed.

 > I think I wrote prep_header_patterns() and compile_grep_patterns()
 > carefully enough not to assume the headers are only the author and
 > committer names, so the various combinations i.e. all-match,
 > author(s), committer(s), grep(s), and reflog-message(s), should
 > work
 > out of the box, but have you actually tested them?

 I did not. I do now, tests are also added.

 On Fri, Sep 28, 2012 at 12:28 AM, Jeff King <peff@peff.net> wrote:
 > I also found the name confusing on first-read. While "--author" is
 > an
 > example in one direction, the fact that "--grep" is not called
 > "--body"
 > is a counter-example.
 >
 > I'd much rather see it as "--grep-reflog" or something. You could
 > also
 > do "--grep-reflog-message", which would match a later
 > "--grep-reflog-author", but I am not sure anybody would want the
 > latter,
 > and it makes the current name a lot longer.

 Changed it to --grep-reflog. I was tempted to add --grep-* but I
 can't error out if user gives an invalid header. So --grep-reflog
 only for now.

 Documentation/rev-list-options.txt |  8 ++++++++
 revision.c                         | 20 ++++++++++++++++++--
 t/t7810-grep.sh                    | 26 ++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 1fc2a18..aa7cd9d 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -51,6 +51,14 @@ endif::git-rev-list[]
 	commits whose author matches any of the given patterns are
 	chosen (similarly for multiple `--committer=<pattern>`).
 
+--grep-reflog=<pattern>::
+
+	Limit the commits output to ones with reflog entries that
+	match the specified pattern (regular expression). With
+	more than one `--grep-reflog`, commits whose reflog message
+	matches any of the given patterns are chosen. Ignored unless
+	`--walk-reflogs` is given.
+
 --grep=<pattern>::
 
 	Limit the commits output to ones with log message that
diff --git a/revision.c b/revision.c
index f7cf385..cfa0e2e 100644
--- a/revision.c
+++ b/revision.c
@@ -1595,6 +1595,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
 		add_header_grep(revs, "committer", optarg);
 		return argcount;
+	} else if ((argcount = parse_long_opt("grep-reflog", argv, &optarg))) {
+		add_header_grep(revs, "reflog", optarg);
+		return argcount;
 	} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
 		add_message_grep(revs, optarg);
 		return argcount;
@@ -2210,10 +2213,23 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
 
 static int commit_match(struct commit *commit, struct rev_info *opt)
 {
+	int retval;
+	struct strbuf buf = STRBUF_INIT;
 	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
 		return 1;
-	return grep_buffer(&opt->grep_filter,
-			   commit->buffer, strlen(commit->buffer));
+	if (opt->reflog_info) {
+		strbuf_addstr(&buf, "reflog ");
+		get_reflog_message(&buf, opt->reflog_info);
+		strbuf_addch(&buf, '\n');
+		strbuf_addstr(&buf, commit->buffer);
+	}
+	if (buf.len)
+		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
+	else
+		retval = grep_buffer(&opt->grep_filter,
+				     commit->buffer, strlen(commit->buffer));
+	strbuf_release(&buf);
+	return retval;
 }
 
 static inline int want_ancestry(struct rev_info *revs)
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 91db352..f42a605 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -546,6 +546,32 @@ test_expect_success 'log grep (6)' '
 	test_cmp expect actual
 '
 
+test_expect_success 'log grep (7)' '
+	git log -g --grep-reflog="commit: third" --pretty=tformat:%s >actual &&
+	echo third >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (8)' '
+	git log -g --grep-reflog="commit: third" --grep-reflog="commit: second" --pretty=tformat:%s >actual &&
+	{
+		echo third && echo second
+	} >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+	git log -g --grep-reflog="commit: third" --author="Thor" --pretty=tformat:%s >actual &&
+	echo third >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+	git log -g --grep-reflog="commit: third" --author="non-existant" --pretty=tformat:%s >actual &&
+	: >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'log with multiple --grep uses union' '
 	git log --grep=i --grep=r --format=%s >actual &&
 	{
-- 
1.7.12.1.405.gb727dc9

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/3] revision: make --grep search in notes too if shown
  2012-09-28  7:01         ` [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers Nguyễn Thái Ngọc Duy
  2012-09-28  7:01           ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
@ 2012-09-28  7:01           ` Nguyễn Thái Ngọc Duy
  2012-09-28 17:55             ` Junio C Hamano
  1 sibling, 1 reply; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-28  7:01 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

Notes are shown after commit body. From user perspective it looks
pretty much like commit body and they may assume --grep would search
in that part too. Make it so.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 On Fri, Sep 28, 2012 at 1:16 AM, Junio C Hamano <gitster@pobox.com>
 wrote:
 > The output from "log --show-notes", on the other hand, is even more
 > conflated and a casual user would view it as part of the message,
 > so
 > I would imagine that if we ever do the extention to cover notes
 > data, the normal "--grep" should apply to it.

 Something like this?

 revision.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/revision.c b/revision.c
index cfa0e2e..febb4d7 100644
--- a/revision.c
+++ b/revision.c
@@ -2223,6 +2223,12 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 		strbuf_addch(&buf, '\n');
 		strbuf_addstr(&buf, commit->buffer);
 	}
+	if (opt->show_notes) {
+		if (!buf.len)
+			strbuf_addstr(&buf, commit->buffer);
+		format_display_notes(commit->object.sha1, &buf,
+				     get_log_output_encoding(), 0);
+	}
 	if (buf.len)
 		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
 	else
-- 
1.7.12.1.405.gb727dc9

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-28  7:01           ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
@ 2012-09-28 17:55             ` Junio C Hamano
  2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
  0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2012-09-28 17:55 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Jeff King

Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:

> Similar to --author/--committer which filters commits by author and
> committer header fields. --grep-reflog adds a fake "reflog" header to
> commit and a grep filter to search on that line.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  On Fri, Sep 28, 2012 at 12:09 AM, Junio C Hamano <gitster@pobox.com>
>  wrote:
>  > I am debating myself if it is sane for this option to have no hint
>  > that it is about "limiting" in its name.  "--author/--committer"
>  > don't and it is clear from the context of the command that they are
>  > not about setting author/committer, so "--reflog-message" may be
>  > interpreted the same, perhaps.
>  >
>  > The entry in the context above talks about multiple occurrence of
>  > that option. Shouldn't this new one also say what happens when it
>  > is
>  > given twice?
>
>  Fixed.
>
>  > I think I wrote prep_header_patterns() and compile_grep_patterns()
>  > carefully enough not to assume the headers are only the author and
>  > committer names, so the various combinations i.e. all-match,
>  > author(s), committer(s), grep(s), and reflog-message(s), should
>  > work
>  > out of the box, but have you actually tested them?
>
>  I did not. I do now, tests are also added.

You seem to have skipped a lot more important comment from the
message that came immediately after the above part.  Did you take a
look at grep.c::match_one_pattern() that calls strip_timestamp() for
any and all GREP_PATTERN_HEAD items?

This is why I think that the [1/3] in this series shows a total lack
of design taste.  Each element in "headers", unlike "body", is a
structured field and its payload has meaning depending on what field
name is associated with it.  That is why we do not give a way to
users to willy-nilly add ad-hoc header fields.

The other side of this coin is that Git ought to be able to take
advantage of the meaning of each header.  Stripping the timestamp
part when doing a textual match against --author/--committer is one
example.  The code in match_one_pattern() to deal with the header
patterns need to be _extended_ to take into account the special
treatment each header, includign this new "reflog " fake header,
wants when doing a textual match, and when we add any other match
against header (either real or fake), we should be able to add
specific matching logic tailored to handle the particular meaning of
the header would have.

For that to happen, the code _must_ know what kind of headers we
would support; discarding the existing enum is going in a wrong
direction.

When we introduce "git log --header=frotz:xyzzy" option that looks
for a generic "frotz " header and tries to see if "xyzzy" textually
appears in the field, we may want to add a generic "this is not a
header that we have special treatment for" enum to the mix.  But for
known kinds of headers, we would need a list of what each header is
and what semantics it wants.

So please reconsider undoing [1/3], and rerolling [2/3] that depends
on it.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3] revision: make --grep search in notes too if shown
  2012-09-28  7:01           ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
@ 2012-09-28 17:55             ` Junio C Hamano
  0 siblings, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2012-09-28 17:55 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Jeff King

Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:

> Notes are shown after commit body. From user perspective it looks
> pretty much like commit body and they may assume --grep would search
> in that part too. Make it so.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  On Fri, Sep 28, 2012 at 1:16 AM, Junio C Hamano <gitster@pobox.com>
>  wrote:
>  > The output from "log --show-notes", on the other hand, is even more
>  > conflated and a casual user would view it as part of the message,
>  > so
>  > I would imagine that if we ever do the extention to cover notes
>  > data, the normal "--grep" should apply to it.
>
>  Something like this?

Yes, that was what I had in mind.

>  revision.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/revision.c b/revision.c
> index cfa0e2e..febb4d7 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -2223,6 +2223,12 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
>  		strbuf_addch(&buf, '\n');
>  		strbuf_addstr(&buf, commit->buffer);
>  	}
> +	if (opt->show_notes) {
> +		if (!buf.len)
> +			strbuf_addstr(&buf, commit->buffer);
> +		format_display_notes(commit->object.sha1, &buf,
> +				     get_log_output_encoding(), 0);
> +	}
>  	if (buf.len)
>  		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
>  	else

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-28 17:55             ` Junio C Hamano
@ 2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
  2012-09-29  4:41                 ` [PATCH 1/3] grep: prepare for new header field filter Nguyễn Thái Ngọc Duy
                                   ` (3 more replies)
  0 siblings, 4 replies; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-29  4:41 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

On Sat, Sep 29, 2012 at 12:55 AM, Junio C Hamano <gitster@pobox.com> wrote:
> For that to happen, the code _must_ know what kind of headers we
> would support; discarding the existing enum is going in a wrong
> direction.

Or what kind of manipulation is required for a header. The caller can
decide if it wants such manipulation or not. Somebody might want to
grep committer's date, for example.

> When we introduce "git log --header=frotz:xyzzy" option that looks
> for a generic "frotz " header and tries to see if "xyzzy" textually
> appears in the field, we may want to add a generic "this is not a
> header that we have special treatment for" enum to the mix.  But for
> known kinds of headers, we would need a list of what each header is
> and what semantics it wants.
>
> So please reconsider undoing [1/3], and rerolling [2/3] that depends
> on it.

Done. The enum is kept. I added a few tests about grepping timestamp
in 1/3 to keep people (or myself) from making the same mistake I did.

3/3 is reposted for completeness, I don't care much about notes (so
far). It's up to you to take or drop it.

Nguyễn Thái Ngọc Duy (3):
  grep: prepare for new header field filter
  revision: add --grep-reflog to filter commits by reflog messages
  revision: make --grep search in notes too if shown

 Documentation/rev-list-options.txt |  8 ++++++++
 grep.c                             | 10 +++++++++-
 grep.h                             |  7 +++++--
 revision.c                         | 26 ++++++++++++++++++++++++--
 t/t7810-grep.sh                    | 38 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 84 insertions(+), 5 deletions(-)

-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/3] grep: prepare for new header field filter
  2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
@ 2012-09-29  4:41                 ` Nguyễn Thái Ngọc Duy
  2012-09-29  5:22                   ` Jeff King
  2012-09-29  4:41                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
                                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-29  4:41 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

grep supports only author and committer headers, which have the same
special treatment that later headers may or may not have. Check for
field type and only strip_timestamp() when the field is either author
or committer.

GREP_HEADER_FIELD_MAX is put in the grep_header_field enum to be
calculated automatically, correctly, as long as it's at the end of the
enum.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 grep.c          |  9 ++++++++-
 grep.h          |  6 ++++--
 t/t7810-grep.sh | 12 ++++++++++++
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/grep.c b/grep.c
index 898be6e..8d73995 100644
--- a/grep.c
+++ b/grep.c
@@ -720,7 +720,14 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 		if (strncmp(bol, field, len))
 			return 0;
 		bol += len;
-		saved_ch = strip_timestamp(bol, &eol);
+		switch (p->field) {
+		case GREP_HEADER_AUTHOR:
+		case GREP_HEADER_COMMITTER:
+			saved_ch = strip_timestamp(bol, &eol);
+			break;
+		default:
+			break;
+		}
 	}
 
  again:
diff --git a/grep.h b/grep.h
index 8a28a67..d54adbe 100644
--- a/grep.h
+++ b/grep.h
@@ -29,9 +29,11 @@ enum grep_context {
 
 enum grep_header_field {
 	GREP_HEADER_AUTHOR = 0,
-	GREP_HEADER_COMMITTER
+	GREP_HEADER_COMMITTER,
+
+	/* Must be at the end of the enum */
+	GREP_HEADER_FIELD_MAX
 };
-#define GREP_HEADER_FIELD_MAX (GREP_HEADER_COMMITTER + 1)
 
 struct grep_pat {
 	struct grep_pat *next;
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 91db352..30eaa9a 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -628,6 +628,18 @@ test_expect_success 'log --all-match --grep --grep --author takes intersection'
 	test_cmp expect actual
 '
 
+test_expect_success 'log --author does not search in timestamp' '
+	: >expect &&
+	git log --author="$GIT_AUTHOR_DATE" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log --committer does not search in timestamp' '
+	: >expect &&
+	git log --committer="$GIT_COMMITTER_DATE" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'grep with CE_VALID file' '
 	git update-index --assume-unchanged t/t &&
 	rm t/t &&
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
  2012-09-29  4:41                 ` [PATCH 1/3] grep: prepare for new header field filter Nguyễn Thái Ngọc Duy
@ 2012-09-29  4:41                 ` Nguyễn Thái Ngọc Duy
  2012-09-29  5:30                   ` Jeff King
  2012-09-29  4:41                 ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
  2012-09-29  5:35                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Junio C Hamano
  3 siblings, 1 reply; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-29  4:41 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

Similar to --author/--committer which filters commits by author and
committer header fields. --grep-reflog adds a fake "reflog" header to
commit and a grep filter to search on that line.

All rules to --author/--committer apply except no timestamp stripping.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/rev-list-options.txt |  8 ++++++++
 grep.c                             |  1 +
 grep.h                             |  1 +
 revision.c                         | 20 ++++++++++++++++++--
 t/t7810-grep.sh                    | 26 ++++++++++++++++++++++++++
 5 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 1fc2a18..aa7cd9d 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -51,6 +51,14 @@ endif::git-rev-list[]
 	commits whose author matches any of the given patterns are
 	chosen (similarly for multiple `--committer=<pattern>`).
 
+--grep-reflog=<pattern>::
+
+	Limit the commits output to ones with reflog entries that
+	match the specified pattern (regular expression). With
+	more than one `--grep-reflog`, commits whose reflog message
+	matches any of the given patterns are chosen. Ignored unless
+	`--walk-reflogs` is given.
+
 --grep=<pattern>::
 
 	Limit the commits output to ones with log message that
diff --git a/grep.c b/grep.c
index 8d73995..d70dcdf 100644
--- a/grep.c
+++ b/grep.c
@@ -697,6 +697,7 @@ static struct {
 } header_field[] = {
 	{ "author ", 7 },
 	{ "committer ", 10 },
+	{ "reflog ", 7 },
 };
 
 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
diff --git a/grep.h b/grep.h
index d54adbe..6e78b96 100644
--- a/grep.h
+++ b/grep.h
@@ -30,6 +30,7 @@ enum grep_context {
 enum grep_header_field {
 	GREP_HEADER_AUTHOR = 0,
 	GREP_HEADER_COMMITTER,
+	GREP_HEADER_REFLOG,
 
 	/* Must be at the end of the enum */
 	GREP_HEADER_FIELD_MAX
diff --git a/revision.c b/revision.c
index ae12e11..109bec1 100644
--- a/revision.c
+++ b/revision.c
@@ -1595,6 +1595,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 	} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
 		add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
 		return argcount;
+	} else if ((argcount = parse_long_opt("grep-reflog", argv, &optarg))) {
+		add_header_grep(revs, GREP_HEADER_REFLOG, optarg);
+		return argcount;
 	} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
 		add_message_grep(revs, optarg);
 		return argcount;
@@ -2210,10 +2213,23 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
 
 static int commit_match(struct commit *commit, struct rev_info *opt)
 {
+	int retval;
+	struct strbuf buf = STRBUF_INIT;
 	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
 		return 1;
-	return grep_buffer(&opt->grep_filter,
-			   commit->buffer, strlen(commit->buffer));
+	if (opt->reflog_info) {
+		strbuf_addstr(&buf, "reflog ");
+		get_reflog_message(&buf, opt->reflog_info);
+		strbuf_addch(&buf, '\n');
+		strbuf_addstr(&buf, commit->buffer);
+	}
+	if (buf.len)
+		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
+	else
+		retval = grep_buffer(&opt->grep_filter,
+				     commit->buffer, strlen(commit->buffer));
+	strbuf_release(&buf);
+	return retval;
 }
 
 static inline int want_ancestry(struct rev_info *revs)
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 30eaa9a..3a5d0fd 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -546,6 +546,32 @@ test_expect_success 'log grep (6)' '
 	test_cmp expect actual
 '
 
+test_expect_success 'log grep (7)' '
+	git log -g --grep-reflog="commit: third" --pretty=tformat:%s >actual &&
+	echo third >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (8)' '
+	git log -g --grep-reflog="commit: third" --grep-reflog="commit: second" --pretty=tformat:%s >actual &&
+	{
+		echo third && echo second
+	} >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+	git log -g --grep-reflog="commit: third" --author="Thor" --pretty=tformat:%s >actual &&
+	echo third >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+	git log -g --grep-reflog="commit: third" --author="non-existant" --pretty=tformat:%s >actual &&
+	: >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'log with multiple --grep uses union' '
 	git log --grep=i --grep=r --format=%s >actual &&
 	{
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/3] revision: make --grep search in notes too if shown
  2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
  2012-09-29  4:41                 ` [PATCH 1/3] grep: prepare for new header field filter Nguyễn Thái Ngọc Duy
  2012-09-29  4:41                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
@ 2012-09-29  4:41                 ` Nguyễn Thái Ngọc Duy
  2012-09-29  5:35                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Junio C Hamano
  3 siblings, 0 replies; 25+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2012-09-29  4:41 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Nguyễn Thái Ngọc Duy

Notes are shown after commit body. From user perspective it looks
pretty much like commit body and they may assume --grep would search
in that part too. Make it so.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 revision.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/revision.c b/revision.c
index 109bec1..dff6fb7 100644
--- a/revision.c
+++ b/revision.c
@@ -2223,6 +2223,12 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 		strbuf_addch(&buf, '\n');
 		strbuf_addstr(&buf, commit->buffer);
 	}
+	if (opt->show_notes) {
+		if (!buf.len)
+			strbuf_addstr(&buf, commit->buffer);
+		format_display_notes(commit->object.sha1, &buf,
+				     get_log_output_encoding(), 0);
+	}
 	if (buf.len)
 		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
 	else
-- 
1.7.12.1.406.g6ab07c4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/3] grep: prepare for new header field filter
  2012-09-29  4:41                 ` [PATCH 1/3] grep: prepare for new header field filter Nguyễn Thái Ngọc Duy
@ 2012-09-29  5:22                   ` Jeff King
  0 siblings, 0 replies; 25+ messages in thread
From: Jeff King @ 2012-09-29  5:22 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Junio C Hamano

On Sat, Sep 29, 2012 at 11:41:27AM +0700, Nguyen Thai Ngoc Duy wrote:

> diff --git a/grep.c b/grep.c
> index 898be6e..8d73995 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -720,7 +720,14 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
>  		if (strncmp(bol, field, len))
>  			return 0;
>  		bol += len;
> -		saved_ch = strip_timestamp(bol, &eol);
> +		switch (p->field) {
> +		case GREP_HEADER_AUTHOR:
> +		case GREP_HEADER_COMMITTER:
> +			saved_ch = strip_timestamp(bol, &eol);
> +			break;
> +		default:
> +			break;
> +		}

Reading this hunk, I wondered what happens to saved_ch if we do not set
it here. Fortunately it is initialized to 0, as we already have to
handle the non-header case. Then later we do this, which does introduce
a new condition (saved_ch was not set, but we trigger the first half of
the conditional):

      if (p->token == GREP_PATTERN_HEAD && saved_ch)
                *eol = saved_ch;

However, the second half of that conditional (which previously was only
triggered when we tried to split the timestamp, but there was a bogus
line with no ">" on it) prevents us from overwriting *eol.

So I think it is good, but it was non-obvious enough that I wanted to
save other reviewers from investigating it.  The rest of the patch looks
good to me, as well.

-Peff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  4:41                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
@ 2012-09-29  5:30                   ` Jeff King
  2012-09-29  5:54                     ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Jeff King @ 2012-09-29  5:30 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Junio C Hamano

On Sat, Sep 29, 2012 at 11:41:28AM +0700, Nguyen Thai Ngoc Duy wrote:

> @@ -2210,10 +2213,23 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
>  
>  static int commit_match(struct commit *commit, struct rev_info *opt)
>  {
> +	int retval;
> +	struct strbuf buf = STRBUF_INIT;
>  	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
>  		return 1;
> -	return grep_buffer(&opt->grep_filter,
> -			   commit->buffer, strlen(commit->buffer));
> +	if (opt->reflog_info) {
> +		strbuf_addstr(&buf, "reflog ");
> +		get_reflog_message(&buf, opt->reflog_info);
> +		strbuf_addch(&buf, '\n');
> +		strbuf_addstr(&buf, commit->buffer);
> +	}
> +	if (buf.len)
> +		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
> +	else
> +		retval = grep_buffer(&opt->grep_filter,
> +				     commit->buffer, strlen(commit->buffer));
> +	strbuf_release(&buf);
> +	return retval;

I like how callers not doing a reflog walk do not have to pay the price
to do the extra allocating. We could further limit it to only when
--grep-reflog is in effect, but I guess that would mean wading through
grep_filter's patterns, since it could be buried amidst ANDs and ORs?

One alternative would be to set a bit in the grep_opt when we call
append_header_grep_pattern. It feels a bit like a layering violation,
though. I guess the bit could also go into rev_info. It may not even be
a measurable slowdown, though. Premature optimization and all that.

Other than that, I didn't notice anything wrong in the patch.

-Peff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
                                   ` (2 preceding siblings ...)
  2012-09-29  4:41                 ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
@ 2012-09-29  5:35                 ` Junio C Hamano
  3 siblings, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2012-09-29  5:35 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Jeff King

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:

> On Sat, Sep 29, 2012 at 12:55 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> For that to happen, the code _must_ know what kind of headers we
>> would support; discarding the existing enum is going in a wrong
>> direction.
>
> Or what kind of manipulation is required for a header. The caller can
> decide if it wants such manipulation or not. Somebody might want to
> grep committer's date, for example.

Yes, if we wanted to filter log outputs to commits authored only on
Thursdays, we would introduce --author-date="<some expression that
yields true only on Thursdays, given the timestmap" option, add
GREP_HEADER_AUTHOR_TIMESTAMP_EXPRESSION=2 to enum grep_header_field,
and add a new element { "author ", 7 } to grep.c::header_field[2]
(the index 2 matches GREP_HEADER_AUTHOR_TIMESTAMP_EXPRESSION), and
implement the evaluator for <some expression that yields true only
on Thursdays, given the timestamp> language in the GREP_PATTERN_HEAD
part of match_one_pattern() and use the p->field to select that
logic.  At that point, we may be better off introducing a helper
function to split the more complex logic for GREP_PATTERN_HEAD out
of the match_one_pattern() function.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  5:30                   ` Jeff King
@ 2012-09-29  5:54                     ` Junio C Hamano
  2012-09-29  6:13                       ` Nguyen Thai Ngoc Duy
  2012-09-29  6:16                       ` Jeff King
  0 siblings, 2 replies; 25+ messages in thread
From: Junio C Hamano @ 2012-09-29  5:54 UTC (permalink / raw)
  To: Jeff King; +Cc: Nguyễn Thái Ngọc Duy, git

Jeff King <peff@peff.net> writes:

>> +	if (opt->reflog_info) {
>> +		strbuf_addstr(&buf, "reflog ");
>> +		get_reflog_message(&buf, opt->reflog_info);
>> +		strbuf_addch(&buf, '\n');
>> +		strbuf_addstr(&buf, commit->buffer);
>> +	}
>> +	if (buf.len)
>> +		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
>> +	else
>> +		retval = grep_buffer(&opt->grep_filter,
>> +				     commit->buffer, strlen(commit->buffer));
>> +	strbuf_release(&buf);
>> +	return retval;
>
> I like how callers not doing a reflog walk do not have to pay the price
> to do the extra allocating. We could further limit it to only when
> --grep-reflog is in effect, but I guess that would mean wading through
> grep_filter's patterns, since it could be buried amidst ANDs and ORs?
>
> One alternative would be to set a bit in the grep_opt when we call
> append_header_grep_pattern. It feels a bit like a layering violation,
> though. I guess the bit could also go into rev_info. It may not even be
> a measurable slowdown, though. Premature optimization and all that.

I do not think it is a layering violation.  compile_grep_exp()
should be aware of the short-cut possibilities and your "our
expression is interested in reflog so we need to read it" is very
similar in spirit to the existing opt->extended bit.

It will obviously allow us to avoid reading reflog information
unnecessarily here.  I think it makes perfect sense.

We may also want to flag the use of the --grep-reflog option when
the --walk-reflogs option is not in effect in setup_revisions() as
an error, or something.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  5:54                     ` Junio C Hamano
@ 2012-09-29  6:13                       ` Nguyen Thai Ngoc Duy
  2012-09-29 19:11                         ` Junio C Hamano
  2012-09-29  6:16                       ` Jeff King
  1 sibling, 1 reply; 25+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-09-29  6:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git

On Sat, Sep 29, 2012 at 12:54 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> I like how callers not doing a reflog walk do not have to pay the price
>> to do the extra allocating. We could further limit it to only when
>> --grep-reflog is in effect, but I guess that would mean wading through
>> grep_filter's patterns, since it could be buried amidst ANDs and ORs?
>>
>> One alternative would be to set a bit in the grep_opt when we call
>> append_header_grep_pattern. It feels a bit like a layering violation,
>> though. I guess the bit could also go into rev_info. It may not even be
>> a measurable slowdown, though. Premature optimization and all that.
>
> I do not think it is a layering violation.  compile_grep_exp()
> should be aware of the short-cut possibilities and your "our
> expression is interested in reflog so we need to read it" is very
> similar in spirit to the existing opt->extended bit.
>
> It will obviously allow us to avoid reading reflog information
> unnecessarily here.  I think it makes perfect sense.

reflog, in terms of both the number of commits and message length, is
usually short enough that slowdown does not really show, especially
when used with git-log, an interactive command.

Without the changes:

$ time git log -g --grep . >/dev/null

real    0m0.480s
user    0m0.451s
sys     0m0.025s

With the changes:

$ time ./git log -g --grep . >/dev/null

real    0m0.490s
user    0m0.471s
sys     0m0.018s

> We may also want to flag the use of the --grep-reflog option when
> the --walk-reflogs option is not in effect in setup_revisions() as
> an error, or something.

That's why I put "Ignored unless --walk-reflogs is given" in the
document. But an error would be fine too. I suppose an error is
preferable in case users do not read document carefully?
-- 
Duy

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  5:54                     ` Junio C Hamano
  2012-09-29  6:13                       ` Nguyen Thai Ngoc Duy
@ 2012-09-29  6:16                       ` Jeff King
  1 sibling, 0 replies; 25+ messages in thread
From: Jeff King @ 2012-09-29  6:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy, git

On Fri, Sep 28, 2012 at 10:54:29PM -0700, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> >> +	if (opt->reflog_info) {
> >> +		strbuf_addstr(&buf, "reflog ");
> >> +		get_reflog_message(&buf, opt->reflog_info);
> >> +		strbuf_addch(&buf, '\n');
> >> +		strbuf_addstr(&buf, commit->buffer);
> >> +	}
> >> +	if (buf.len)
> >> +		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
> >> +	else
> >> +		retval = grep_buffer(&opt->grep_filter,
> >> +				     commit->buffer, strlen(commit->buffer));
> >> +	strbuf_release(&buf);
> >> +	return retval;
> >
> > I like how callers not doing a reflog walk do not have to pay the price
> > to do the extra allocating. We could further limit it to only when
> > --grep-reflog is in effect, but I guess that would mean wading through
> > grep_filter's patterns, since it could be buried amidst ANDs and ORs?
> >
> > One alternative would be to set a bit in the grep_opt when we call
> > append_header_grep_pattern. It feels a bit like a layering violation,
> > though. I guess the bit could also go into rev_info. It may not even be
> > a measurable slowdown, though. Premature optimization and all that.
> 
> I do not think it is a layering violation.  compile_grep_exp()
> should be aware of the short-cut possibilities and your "our
> expression is interested in reflog so we need to read it" is very
> similar in spirit to the existing opt->extended bit.

Hmm. Yeah, I guess so. I was thinking that the grep code did not know
there was a commit or reflog involved at all (we just pass it a buffer,
and how we prepare it is our business), but it does already know about
the magic GREP_HEADER_* variables, and this is definitely part of that.

> We may also want to flag the use of the --grep-reflog option when
> the --walk-reflogs option is not in effect in setup_revisions() as
> an error, or something.

Good point. I think the docs in the patch just say it is ignored unless
walking, but it would be better to flag the error.

-Peff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29  6:13                       ` Nguyen Thai Ngoc Duy
@ 2012-09-29 19:11                         ` Junio C Hamano
  2012-09-30  3:45                           ` Nguyen Thai Ngoc Duy
  0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2012-09-29 19:11 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: Jeff King, git

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

> reflog, in terms of both the number of commits and message length, is
> usually short enough that slowdown does not really show, especially
> when used with git-log, an interactive command.

You shouldn't do things you can easily tell you do not need to,
especially when the effort to avoid doing unnecessary allocation,
copying and deallocation is not excessively larger than the saving.

I personally think that lack of perceived performance impact is not
an excuse to be sloppy. These things tend to add up.

> That's why I put "Ignored unless --walk-reflogs is given" in the
> document. But an error would be fine too. I suppose an error is
> preferable in case users do not read document carefully?


A reader who reads documentation carefully will spot that it is a
sloppy coding that such a nonsense combination of two options are
not caught and diagnosed as an error, when accepting and silently
ignoring the option would not help anybody.

An alternative may be to turn -g on when --grep-reflog is given.
Starting from a version that forbids --grep-reflog without -g will
let us change the command line parser to do so in the future without
backward incompatibility, but you cannot do so if you start from a
version that accepts and silently ignores.

How about squashing this in?  I've future-proofed commit_match() a
bit while at it; it would be cleaner to add new fake headers if the
function is done this way.

 Documentation/rev-list-options.txt |  4 ++--
 grep.c                             |  2 ++
 grep.h                             |  1 +
 revision.c                         | 13 +++++++++++--
 t/t7810-grep.sh                    |  4 ++++
 5 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index aa7cd9d..ca22106 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -56,8 +56,8 @@ endif::git-rev-list[]
 	Limit the commits output to ones with reflog entries that
 	match the specified pattern (regular expression). With
 	more than one `--grep-reflog`, commits whose reflog message
-	matches any of the given patterns are chosen. Ignored unless
-	`--walk-reflogs` is given.
+	matches any of the given patterns are chosen.  It is an
+	error to use this option unless `--walk-reflogs` is in use.
 
 --grep=<pattern>::
 
diff --git a/grep.c b/grep.c
index d70dcdf..edc7776 100644
--- a/grep.c
+++ b/grep.c
@@ -64,6 +64,8 @@ void append_header_grep_pattern(struct grep_opt *opt,
 {
 	struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
 					     GREP_PATTERN_HEAD, field);
+	if (field == GREP_HEADER_REFLOG)
+		opt->use_reflog_filter = 1;
 	do_append_grep_pat(&opt->header_tail, p);
 }
 
diff --git a/grep.h b/grep.h
index 6e78b96..c256ac6 100644
--- a/grep.h
+++ b/grep.h
@@ -107,6 +107,7 @@ struct grep_opt {
 #define GREP_BINARY_TEXT	2
 	int binary;
 	int extended;
+	int use_reflog_filter;
 	int pcre;
 	int relative;
 	int pathname;
diff --git a/revision.c b/revision.c
index 109bec1..9ad72df 100644
--- a/revision.c
+++ b/revision.c
@@ -1908,6 +1908,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
 
 	if (revs->reflog_info && revs->graph)
 		die("cannot combine --walk-reflogs with --graph");
+	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
+		die("cannot use --grep-reflog without --walk-reflogs");
 
 	return left;
 }
@@ -2217,12 +2219,19 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
 	struct strbuf buf = STRBUF_INIT;
 	if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
 		return 1;
-	if (opt->reflog_info) {
+
+	/* Prepend "fake" headers as needed */
+	if (opt->grep_filter.use_reflog_filter) {
 		strbuf_addstr(&buf, "reflog ");
 		get_reflog_message(&buf, opt->reflog_info);
 		strbuf_addch(&buf, '\n');
-		strbuf_addstr(&buf, commit->buffer);
 	}
+
+	/* Copy the commit to temporary if we are using "fake" headers */
+	if (buf.len)
+		strbuf_addstr(&buf, commit->buffer);
+
+	/* Find either in the commit object, or in the temporary */
 	if (buf.len)
 		retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
 	else
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 3a5d0fd..f698001 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -572,6 +572,10 @@ test_expect_success 'log grep (9)' '
 	test_cmp expect actual
 '
 
+test_expect_success 'log --grep-reflog can only be used under -g' '
+	test_must_fail git log --grep-reflog="commit: third"
+'
+
 test_expect_success 'log with multiple --grep uses union' '
 	git log --grep=i --grep=r --format=%s >actual &&
 	{
-- 
1.7.12.1.484.g1764bc0

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages
  2012-09-29 19:11                         ` Junio C Hamano
@ 2012-09-30  3:45                           ` Nguyen Thai Ngoc Duy
  0 siblings, 0 replies; 25+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2012-09-30  3:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, git

On Sun, Sep 30, 2012 at 2:11 AM, Junio C Hamano <gitster@pobox.com> wrote:
> How about squashing this in?  I've future-proofed commit_match() a
> bit while at it; it would be cleaner to add new fake headers if the
> function is done this way.

Sure. It looks good to me.

> --- a/Documentation/rev-list-options.txt
> +++ b/Documentation/rev-list-options.txt
> @@ -56,8 +56,8 @@ endif::git-rev-list[]
>         Limit the commits output to ones with reflog entries that
>         match the specified pattern (regular expression). With
>         more than one `--grep-reflog`, commits whose reflog message
> -       matches any of the given patterns are chosen. Ignored unless
> -       `--walk-reflogs` is given.
> +       matches any of the given patterns are chosen.  It is an
> +       error to use this option unless `--walk-reflogs` is in use.

We could even drop the part about --walk-reflogs. Users will soon
figure it out when they try it.
-- 
Duy

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2012-09-30  3:47 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-26 12:12 [PATCH] revision: add --reflog-message=<pattern> to grep reflog messages Nguyễn Thái Ngọc Duy
2012-09-26 14:07 ` Junio C Hamano
2012-09-26 14:15   ` Nguyen Thai Ngoc Duy
2012-09-26 19:28     ` Junio C Hamano
2012-09-27 11:36       ` [PATCH] revision: add --reflog-message " Nguyễn Thái Ngọc Duy
2012-09-27 17:09         ` Junio C Hamano
2012-09-27 17:28           ` Jeff King
2012-09-27 18:16             ` Junio C Hamano
2012-09-28  7:01         ` [PATCH 1/3] grep: generalize header grep code to accept arbitrary headers Nguyễn Thái Ngọc Duy
2012-09-28  7:01           ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
2012-09-28 17:55             ` Junio C Hamano
2012-09-29  4:41               ` Nguyễn Thái Ngọc Duy
2012-09-29  4:41                 ` [PATCH 1/3] grep: prepare for new header field filter Nguyễn Thái Ngọc Duy
2012-09-29  5:22                   ` Jeff King
2012-09-29  4:41                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Nguyễn Thái Ngọc Duy
2012-09-29  5:30                   ` Jeff King
2012-09-29  5:54                     ` Junio C Hamano
2012-09-29  6:13                       ` Nguyen Thai Ngoc Duy
2012-09-29 19:11                         ` Junio C Hamano
2012-09-30  3:45                           ` Nguyen Thai Ngoc Duy
2012-09-29  6:16                       ` Jeff King
2012-09-29  4:41                 ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
2012-09-29  5:35                 ` [PATCH 2/3] revision: add --grep-reflog to filter commits by reflog messages Junio C Hamano
2012-09-28  7:01           ` [PATCH 3/3] revision: make --grep search in notes too if shown Nguyễn Thái Ngọc Duy
2012-09-28 17:55             ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).