{"thread":{"id":"31504","subject":"[PATCH] rev-list/log: document logic with several limiting options","startedAt":"2012-09-11T14:45:53Z","lastAt":"2012-09-14T18:01:09Z","messageCount":43,"participants":["Michael J Gruber","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"198780","messageId":"b23f3c547358b79731c7a25d9ac496138e6ab74d.1347374615.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":null,"subject":"[PATCH] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-11T14:45:53Z","receivedAt":"2012-09-11T14:45:53Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"The current behavior is probably as useful as it is confusing. In any\ncase it is going to stay. So, document it.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\nI would have written a test but don't really know where to stick it in.\nrev-list has many small tests where it doesn't fit.\n\n Documentation/rev-list-options.txt | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 5436eba..9c13df3 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -6,6 +6,12 @@ special notations explained in the description, additional commit\n limiting may be applied. Note that they are applied before commit\n ordering and formatting options, such as '--reverse'.\n \n+All occurrences of the same option are ORed: '--grep=foo --grep=bar'\n+limits to commits which match at least one of these conditions.\n+\n+Different options are ANDed: '--author=bar --grep=foo'\n+limits to commits which match both conditions.\n+\n --\n \n -n 'number'::\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198793","messageId":"7vsjaoil6d.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"b23f3c547358b79731c7a25d9ac496138e6ab74d.1347374615.git.git@drmicha.warpmail.net","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-11T16:22:34Z","receivedAt":"2012-09-11T16:22:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> The current behavior is probably as useful as it is confusing. In any\n> case it is going to stay. So, document it.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n> I would have written a test but don't really know where to stick it in.\n> rev-list has many small tests where it doesn't fit.\n\n\"git log\" would be the more natural place, I would say.\n\n>\n>  Documentation/rev-list-options.txt | 6 ++++++\n>  1 file changed, 6 insertions(+)\n>\n> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n> index 5436eba..9c13df3 100644\n> --- a/Documentation/rev-list-options.txt\n> +++ b/Documentation/rev-list-options.txt\n> @@ -6,6 +6,12 @@ special notations explained in the description, additional commit\n>  limiting may be applied. Note that they are applied before commit\n>  ordering and formatting options, such as '--reverse'.\n>  \n> +All occurrences of the same option are ORed: '--grep=foo --grep=bar'\n> +limits to commits which match at least one of these conditions.\n\nHow would this interact with \"--all-match\"?\n"},{"id":"198835","messageId":"50509171.9060604@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vsjaoil6d.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-12T13:43:13Z","receivedAt":"2012-09-12T13:43:13Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 11.09.2012 18:22:\n> Michael J Gruber <git@drmicha.warpmail.net> writes:\n> \n>> The current behavior is probably as useful as it is confusing. In any\n>> case it is going to stay. So, document it.\n>>\n>> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n>> ---\n>> I would have written a test but don't really know where to stick it in.\n>> rev-list has many small tests where it doesn't fit.\n> \n> \"git log\" would be the more natural place, I would say.\n\nWell, to me, \"git log\" is the ui to \"git rev-list\", so everything which\ntests the revision walker should be tested using \"git rev-list\". But I\ndon't care as long as it fits in - and can be found later.\n\nThat being said, I now see lots of \"log --grep\" and \"log --author\" tests\nin the grep-test. So I guess there it fits best (despite the misnomer).\n\n>>\n>>  Documentation/rev-list-options.txt | 6 ++++++\n>>  1 file changed, 6 insertions(+)\n>>\n>> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n>> index 5436eba..9c13df3 100644\n>> --- a/Documentation/rev-list-options.txt\n>> +++ b/Documentation/rev-list-options.txt\n>> @@ -6,6 +6,12 @@ special notations explained in the description, additional commit\n>>  limiting may be applied. Note that they are applied before commit\n>>  ordering and formatting options, such as '--reverse'.\n>>  \n>> +All occurrences of the same option are ORed: '--grep=foo --grep=bar'\n>> +limits to commits which match at least one of these conditions.\n> \n> How would this interact with \"--all-match\"?\n\nBadly.\n\nIt was introduced in 0ab7befa with a clear meaning (AND everything),\nthen the general logic (without --all-match) was modified in 80235ba7\n(to take headermatch AND (all greps ORed)), and 5aaeb733 finally made\nmultiple authors resp. committers get ORed among each other. All of this\nin an attempt to make the standard usage most useful, of course. As a\nconsequence, --all-match does not influence multiple --author options at\nall (contrary to the doc), e.g.\n\nI don't see any of this reflected in the doc, though. I noticed only by\nreading t/t7810-grep.sh. Before that, I had only gone by my own testing\nwhich didn't reveal the multiple author multiple special casing effect.\n\nI guess I'll have to wrap my head around the current implementation a\nfew more times before trying to describe the status quo in the\ndocumentation...\n"},{"id":"198856","messageId":"7vbohbdufz.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"50509171.9060604@drmicha.warpmail.net","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-12T17:25:52Z","receivedAt":"2012-09-12T17:25:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> It was introduced in 0ab7befa with a clear meaning (AND everything),\n> then the general logic (without --all-match) was modified in 80235ba7\n> (to take headermatch AND (all greps ORed)), and 5aaeb733 finally made\n> multiple authors resp. committers get ORed among each other. All of this\n> in an attempt to make the standard usage most useful, of course. As a\n> consequence, --all-match does not influence multiple --author options at\n> all (contrary to the doc), e.g.\n>\n> I don't see any of this reflected in the doc, though. I noticed only by\n> reading t/t7810-grep.sh. Before that, I had only gone by my own testing\n> which didn't reveal the multiple author multiple special casing effect.\n>\n> I guess I'll have to wrap my head around the current implementation a\n> few more times before trying to describe the status quo in the\n> documentation...\n\nThis is what I used to use when adding these generalized grep\nboolean expressions.\n\nWith this applied, you can try things like these:\n\n    $ git log --grep=regexp --grep=nosuch --all-match >/dev/null\n    $ git log --grep=regexp --grep=nosuch --author=Michael >/dev/null\n\nFor example, \"--all-match --grep=regexp --author=Michael --author=Linus\" turns\ninto\n\n    [all-match]\n    (or\n     pattern_body<body>regexp\n     (or\n      (or\n       pattern_head<head 0>Linus\n       pattern_head<head 0>Michael\n      )\n      true\n     )\n    )\n\nthat says \"body must have 'regexp' in it, and authored by either\nLinus or Michael\".\n\nThe semantics of \"--all-match\" is different from \"--and\" (which,\ntogether with \"--or\", \")\", and \"(\", is not availble to rev-list\ncommand line parser primarily because \"--not\" is not available).\nAfter applying all the \"or\"-ed terms, it checks the top-level nodes\nthat are \"or\"-ed and makes sure all of them fired (possibly and\nusually on different lines).\n"},{"id":"198857","messageId":"7v7grzdue6.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"7vbohbdufz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-12T17:26:57Z","receivedAt":"2012-09-12T17:26:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> This is what I used to use when adding these generalized grep\n> boolean expressions.\n>\n> With this applied,...\n\nAnd this is the \"this\" X-<.\n\n grep.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 89 insertions(+), 1 deletion(-)\n\ndiff --git a/grep.c b/grep.c\nindex 04e3ec6..566c4cc 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -332,6 +332,87 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)\n \treturn compile_pattern_or(list);\n }\n \n+static void indent(int in)\n+{\n+\twhile (in-- > 0)\n+\t\tfputc(' ', stderr);\n+}\n+\n+static void dump_grep_pat(struct grep_pat *p)\n+{\n+\tswitch (p->token) {\n+\tcase GREP_AND: fprintf(stderr, \"*and*\"); break;\n+\tcase GREP_OPEN_PAREN: fprintf(stderr, \"*(*\"); break;\n+\tcase GREP_CLOSE_PAREN: fprintf(stderr, \"*)*\"); break;\n+\tcase GREP_NOT: fprintf(stderr, \"*not*\"); break;\n+\tcase GREP_OR: fprintf(stderr, \"*or*\"); break;\n+\n+\tcase GREP_PATTERN: fprintf(stderr, \"pattern\"); break;\n+\tcase GREP_PATTERN_HEAD: fprintf(stderr, \"pattern_head\"); break;\n+\tcase GREP_PATTERN_BODY: fprintf(stderr, \"pattern_body\"); break;\n+\t}\n+\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\t\tfprintf(stderr, \"<head %d>\", p->field); break;\n+\tcase GREP_PATTERN_BODY:\n+\t\tfprintf(stderr, \"<body>\"); break;\n+\t}\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\tcase GREP_PATTERN_BODY:\n+\tcase GREP_PATTERN:\n+\t\tfprintf(stderr, \"%.*s\", (int)p->patternlen, p->pattern);\n+\t\tbreak;\n+\t}\n+\tfputc('\\n', stderr);\n+}\n+\n+static void dump_grep_expression_1(struct grep_expr *x, int in)\n+{\n+\tindent(in);\n+\tswitch (x->node) {\n+\tcase GREP_NODE_TRUE:\n+\t\tfprintf(stderr, \"true\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_ATOM:\n+\t\tdump_grep_pat(x->u.atom);\n+\t\tbreak;\n+\tcase GREP_NODE_NOT:\n+\t\tfprintf(stderr, \"(not\\n\");\n+\t\tdump_grep_expression_1(x->u.unary, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_AND:\n+\t\tfprintf(stderr, \"(and\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_OR:\n+\t\tfprintf(stderr, \"(or\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\t}\n+}\n+\n+void dump_grep_expression(struct grep_opt *opt)\n+{\n+\tstruct grep_expr *x = opt->pattern_expression;\n+\n+\tif (opt->all_match)\n+\t\tfprintf(stderr, \"[all-match]\\n\");\n+\tdump_grep_expression_1(x, 0);\n+\tfflush(NULL);\n+}\n+\n static struct grep_expr *grep_true_expr(void)\n {\n \tstruct grep_expr *z = xcalloc(1, sizeof(*z));\n@@ -395,7 +476,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \treturn header_expr;\n }\n \n-void compile_grep_patterns(struct grep_opt *opt)\n+static void compile_grep_patterns_real(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n \tstruct grep_expr *header_expr = prep_header_patterns(opt);\n@@ -432,9 +513,16 @@ void compile_grep_patterns(struct grep_opt *opt)\n \telse\n \t\topt->pattern_expression = grep_or_expr(opt->pattern_expression,\n \t\t\t\t\t\t       header_expr);\n+\n \topt->all_match = 1;\n }\n \n+void compile_grep_patterns(struct grep_opt *opt)\n+{\n+\tcompile_grep_patterns_real(opt);\n+\tdump_grep_expression(opt);\n+}\n+\n static void free_pattern_expr(struct grep_expr *x)\n {\n \tswitch (x->node) {\n-- \n1.7.12.414.g1a62b7a\n"},{"id":"198905","messageId":"50518B13.5010702@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vbohbdufz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T07:28:19Z","receivedAt":"2012-09-13T07:28:19Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 12.09.2012 19:25:\n> Michael J Gruber <git@drmicha.warpmail.net> writes:\n> \n>> It was introduced in 0ab7befa with a clear meaning (AND everything),\n>> then the general logic (without --all-match) was modified in 80235ba7\n>> (to take headermatch AND (all greps ORed)), and 5aaeb733 finally made\n>> multiple authors resp. committers get ORed among each other. All of this\n>> in an attempt to make the standard usage most useful, of course. As a\n>> consequence, --all-match does not influence multiple --author options at\n>> all (contrary to the doc), e.g.\n>>\n>> I don't see any of this reflected in the doc, though. I noticed only by\n>> reading t/t7810-grep.sh. Before that, I had only gone by my own testing\n>> which didn't reveal the multiple author multiple special casing effect.\n>>\n>> I guess I'll have to wrap my head around the current implementation a\n>> few more times before trying to describe the status quo in the\n>> documentation...\n> \n> This is what I used to use when adding these generalized grep\n> boolean expressions.\n> \n> With this applied, you can try things like these:\n> \n>     $ git log --grep=regexp --grep=nosuch --all-match >/dev/null\n>     $ git log --grep=regexp --grep=nosuch --author=Michael >/dev/null\n> \n> For example, \"--all-match --grep=regexp --author=Michael --author=Linus\" turns\n> into\n> \n>     [all-match]\n>     (or\n>      pattern_body<body>regexp\n>      (or\n>       (or\n>        pattern_head<head 0>Linus\n>        pattern_head<head 0>Michael\n>       )\n>       true\n>      )\n>     )\n> \n> that says \"body must have 'regexp' in it, and authored by either\n> Linus or Michael\".\n> \n> The semantics of \"--all-match\" is different from \"--and\" (which,\n> together with \"--or\", \")\", and \"(\", is not availble to rev-list\n> command line parser primarily because \"--not\" is not available).\n> After applying all the \"or\"-ed terms, it checks the top-level nodes\n> that are \"or\"-ed and makes sure all of them fired (possibly and\n> usually on different lines).\n\nThanks for \"this\" ;)\n\nI'll recheck my understanding and update the doc then. Maybe even\nputting the above in-tree with a \"--debug\" option seems inline with\nthings such as \"git describe --debug\" (and maybe a preparation for\nexposing a richer interface).\n\nMichael\n"},{"id":"198918","messageId":"cover.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 0/6] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:38Z","receivedAt":"2012-09-13T14:04:38Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"So, this turned out to be a bit longer.\nI decided not to implement \"--debug\" for \"git log --grep\" and such\nbecause the current code does a lot of special casing, so that the\nexisting debug code happily outputs OR nodes in cases where the code\nin grep.c effectively does AND (without changing the expression nodes).\n\nSo, this series sets up a few more tests to prove to myself that I'm not\ncompletely off in my understanding of the limiting options, and to make\nme confident enough for the documentation patch 6/6 (v2 of the old 1/1).\n\n5/6 documents (by a test) an issue which I consider a (now) known failure:\n'git log --all-match --author=me --grep=foo --grep=bar' does not AND the\ngreps (whereas it does without --author). I don't describe this corner\ncase in the doc patch.\n\nMichael J Gruber (6):\n  t7810-grep: bring log --grep tests in common form\n  t7810-grep: test multiple --grep with and without --all-match\n  t7810-grep: test multiple --author with --all-match\n  t7810-grep: test interaction of multiple --grep and --author options\n  t7810-grep: test --all-match with multiple --grep and --author\n    options\n  rev-list/log: document logic with several limiting options\n\n Documentation/rev-list-options.txt | 15 ++++++-\n t/t7810-grep.sh                    | 90 ++++++++++++++++++++++++++++++++------\n 2 files changed, 90 insertions(+), 15 deletions(-)\n\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198919","messageId":"cbc677f1acfc4d2f29d69e7f6d4b1b780f6e40dd.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 1/6] t7810-grep: bring log --grep tests in common form","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:39Z","receivedAt":"2012-09-13T14:04:39Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"The log --grep tests generate the expected out in different ways.\nMake them all use command blocks so that subshells are avoided and the\nexpected output is easier to grasp visually.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 24 ++++++++++++++++++------\n 1 file changed, 18 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 35d357d..9b683ac 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -502,31 +502,41 @@ test_expect_success 'log grep setup' '\n \n test_expect_success 'log grep (1)' '\n \tgit log --author=author --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (2)' '\n \tgit log --author=\" * \" -F --pretty=tformat:%s >actual &&\n-\t( echo second ) >expect &&\n+\t{\n+\t\techo second\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (3)' '\n \tgit log --author=\"^A U\" --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (4)' '\n \tgit log --author=\"frotz\\.com>$\" --pretty=tformat:%s >actual &&\n-\t( echo second ) >expect &&\n+\t{\n+\t\techo second\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (5)' '\n \tgit log --author=Thor -F --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -540,7 +550,9 @@ test_expect_success 'log --grep --author implicitly uses all-match' '\n \t# grep matches initial and second but not third\n \t# author matches only initial and third\n \tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n-\techo initial >expect &&\n+\t{\n+\t\techo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n1.7.12.463.gbd9d638\n"},{"id":"198920","messageId":"4a63f5bb100308e476c387e97b8e1fb64483d1a2.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 2/6] t7810-grep: test multiple --grep with and without --all-match","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:40Z","receivedAt":"2012-09-13T14:04:40Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 16 ++++++++++++++++\n 1 file changed, 16 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 9b683ac..1db3dcb 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -546,6 +546,22 @@ test_expect_success 'log grep (6)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log with multiple --grep uses union' '\n+\tgit log --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo fourth && echo third && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --all-match with multiple --grep uses intersection' '\n+\tgit log --all-match --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo third\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log --grep --author implicitly uses all-match' '\n \t# grep matches initial and second but not third\n \t# author matches only initial and third\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198923","messageId":"8fd93bb87098298677426735dd354fa4f64abc17.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 3/6] t7810-grep: test multiple --author with --all-match","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:41Z","receivedAt":"2012-09-13T14:04:41Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"--all-match is ignored for author matching on purpose.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 8 ++++++++\n 1 file changed, 8 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 1db3dcb..9bc63a3 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -580,6 +580,14 @@ test_expect_success 'log with multiple --author uses union' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --all-match with multiple --author still uses union' '\n+\tgit log --all-match --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n+\t{\n+\t    echo third && echo second && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log with --grep and multiple --author uses all-match' '\n \tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n \t{\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198924","messageId":"dfbe954c5248a41740fc120be0fe425ecf1f06ca.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 4/6] t7810-grep: test interaction of multiple --grep and --author options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:42Z","receivedAt":"2012-09-13T14:04:42Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"There are tests for this interaction already. Restructure slightly and\navoid any claims about --all-match.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 38 ++++++++++++++++++++++----------------\n 1 file changed, 22 insertions(+), 16 deletions(-)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 9bc63a3..f98f3f6 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -562,16 +562,6 @@ test_expect_success 'log --all-match with multiple --grep uses intersection' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log --grep --author implicitly uses all-match' '\n-\t# grep matches initial and second but not third\n-\t# author matches only initial and third\n-\tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n-\t{\n-\t\techo initial\n-\t} >expect &&\n-\ttest_cmp expect actual\n-'\n-\n test_expect_success 'log with multiple --author uses union' '\n \tgit log --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n \t{\n@@ -588,17 +578,33 @@ test_expect_success 'log --all-match with multiple --author still uses union' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log with --grep and multiple --author uses all-match' '\n-\tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+test_expect_success 'log --grep --author uses intersection' '\n+\t# grep matches only third and fourth\n+\t# author matches only initial and third\n+\tgit log --author=\"A U Thor\" --grep=r --format=%s >actual &&\n \t{\n-\t    echo third && echo initial\n+\t\techo third\n \t} >expect &&\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log with --grep and multiple --author uses all-match' '\n-\tgit log --author=\"Thor\" --author=\"Night\" --grep=q --format=%s >actual &&\n-\t>expect &&\n+test_expect_success 'log --grep --grep --author takes union of greps and intersects with author' '\n+\t# grep matches initial and second but not third\n+\t# author matches only initial and third\n+\tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n+\t{\n+\t\techo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '\n+\t# grep matches only initial and third\n+\t# author matches all but second\n+\tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+\t{\n+\t    echo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n1.7.12.463.gbd9d638\n"},{"id":"198922","messageId":"fec86dc5c7b7cfbc99b887d90dac7519ddd0ba1f.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 5/6] t7810-grep: test --all-match with multiple --grep and --author options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:43Z","receivedAt":"2012-09-13T14:04:43Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"--all-match is ignored with multiple author options on purpose.\nIt is also ignored with multiple --grep options when an --author option\nis present. Mark this as known failure.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 20 ++++++++++++++++++++\n 1 file changed, 20 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex f98f3f6..fa2845f 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -598,6 +598,16 @@ test_expect_success 'log --grep --grep --author takes union of greps and interse\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log ---all-match -grep --author --author still takes union of authors and intersects with grep' '\n+\t# grep matches only initial and third\n+\t# author matches all but second\n+\tgit log --all-match --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+\t{\n+\t    echo third && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '\n \t# grep matches only initial and third\n \t# author matches all but second\n@@ -608,6 +618,16 @@ test_expect_success 'log --grep --author --author takes union of authors and int\n \ttest_cmp expect actual\n '\n \n+test_expect_failure 'log --all-match --grep --grep --author takes intersection' '\n+\t# grep matches only third\n+\t# author matches only initial and third\n+\tgit log --all-match --author=\"A U Thor\" --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo third\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'grep with CE_VALID file' '\n \tgit update-index --assume-unchanged t/t &&\n \trm t/t &&\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198921","messageId":"49f89f65cd39306655a9b382a1244e34fb90fff1.1347544259.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7v7grzdue6.fsf@alter.siamese.dyndns.org","subject":"[PATCHv2 6/6] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-13T14:04:44Z","receivedAt":"2012-09-13T14:04:44Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"The current behavior is probably as useful as it is confusing. In any\ncase it is going to stay. So, document it.\n\nThis does not take into account the issue of 'log --all-match\n--author=me --grep=foo --grep=bar' not honoring '--all-match' because it\nis hopefully a corner case (and, even more hopefully, fixed some time\nsoon).\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n Documentation/rev-list-options.txt | 15 ++++++++++++++-\n 1 file changed, 14 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 5436eba..b2dbfb5 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -6,6 +6,19 @@ special notations explained in the description, additional commit\n limiting may be applied. Note that they are applied before commit\n ordering and formatting options, such as '--reverse'.\n \n+Different options are ANDed: '--author=bar --grep=foo'\n+limits to commits which match both conditions.\n+\n+Several occurences of the '--grep' option are ORed: '--grep=foo --grep=bar'\n+limits to commits matching any of these conditions.\n+(If '--all-match' is given, the conditions are ANDed.)\n+\n+Several occurences of the '--author' and '--committer' options are ORed\n+(because there can be only one each per commit).\n+\n+For all other options, only the last occurence of the same option is\n+taken into account: '-n 5 -3' is '-3' and '-n 3 -n 5' is '-n 5'.\n+\n --\n \n -n 'number'::\n@@ -47,7 +60,7 @@ endif::git-rev-list[]\n \n --all-match::\n \tLimit the commits output to ones that match all given --grep,\n-\t--author and --committer instead of ones that match at least one.\n+\tinstead of ones that match at least one.\n \n -i::\n --regexp-ignore-case::\n-- \n1.7.12.463.gbd9d638\n"},{"id":"198961","messageId":"7vr4q57k2o.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"cover.1347544259.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv2 0/6] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-13T20:18:39Z","receivedAt":"2012-09-13T20:18:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> So, this turned out to be a bit longer.\n> I decided not to implement \"--debug\" for \"git log --grep\" and such\n> because the current code does a lot of special casing, so that the\n> existing debug code happily outputs OR nodes in cases where the code\n> in grep.c effectively does AND (without changing the expression nodes).\n\nIs that something we (not necessarily you) would want to fix?  How\nmany are they?\n\nThe reason I am asking is because I do not think of any.  The entire\ndocument is considered unmatched unless all of the OR nodes in the\ntop-level backbone have triggered for some line in the document when\n\"all-match\" is in effect, but that is quite different from turning\nOR nodes into AND nodes (they both are about \"does this line match\nthe pattern?\"), so...\n"},{"id":"198963","messageId":"7vmx0t7iq0.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"8fd93bb87098298677426735dd354fa4f64abc17.1347544259.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv2 3/6] t7810-grep: test multiple --author with --all-match","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-13T20:47:51Z","receivedAt":"2012-09-13T20:47:51Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> --all-match is ignored for author matching on purpose.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n\nWhat the added test expects is correct, but I do not think the above\ndescription is correct.  \"all-match\" is implicitly turned on when\nyou use header match.\n\nWhen you say\n\n\tgit log --grep=Linus --grep=Junio\n\nyou will get\n\n    (or\n     pattern_body<body>Junio\n     pattern_body<body>Linus\n    )\n\nbut when you say\n\n\tgit log --author=Linus --author=Junio\n\nyou will get\n\n    [all-match]\n    (or\n     (or\n      pattern_head<head 0>Linus\n      pattern_head<head 0>Junio\n     )\n     true\n    )\n\ninstead.  Notice that there is one extra level of \"OR\" node, so that\ntwo OR nodes on the top-level backbone (think of these as cons cells\nwith car and cdr) are \"author is either Linus or junio\" and \"True\".\nBecause \"all-match\" is about rejecting a document as non-matching\nunless all the OR nodes on the top-level backbone have fired, this\nallows commit that is authored either by Linus or by Junio to match,\nand \"on purpose\" part in your message is correct.\n\nBut\n\n\tgit log --author=Linus --author=Junio --grep=commit\n\nwill be parsed to\n\n    [all-match]\n    (or\n     pattern_body<body>commit\n     (or\n      (or\n       pattern_head<head 0>Linus\n       pattern_head<head 0>Junio\n      )\n      true\n     )\n    )\n\nto have three OR nodes on the backbone: \"the log message must have commit\",\n\"authored by either Linus or Junio\", and \"true\".  All three must\nmatch somewhere in the \"git cat-file commit\" output for the commit\nto be considered a match (but obviously they do not have to match on\nthe same line).\n\nSo what is giving commits made by Linus, even though it is not\nauthored by Junio, with \"--author=Linus --author=Junio\" is not the\nlack of --all-match.  In fact, --all-match is implicitly set for\nother things, so that the last example finds commits that mention\n\"commit\" authored by one of these two people.  Commits that do\nmention \"commit\" but are done by other people are excluded.  Commits\nthat do not mention \"commit\" are excluded even if they were done by\nLinus or Junio.\n\n\tgit log --committer=Linus --author=Junio\n\nturns into\n\n    [all-match]\n    (or\n     pattern_head<head 1>Linus\n     (or\n      pattern_head<head 0>Junio\n      true\n     )\n    )\n\nwhich has \"committed by Linus\", \"authored by Junio\" on the top-level\nbackbone, so both has to be true for a commit to match.\n\nAdding --grep=commit makes it\n\n    [all-match]\n    (or\n     pattern_body<body>commit\n     (or\n      pattern_head<head 1>Linus\n      (or\n       pattern_head<head 0>Junio\n       true\n      )\n     )\n    )\n\nwhich has \"committed by Linus\", \"authored by Junio\", \"mentions\ncommit\" on the top-level, and all three has to be true.\n\n\tgit log --committer=Linus --author=Junio --grep=commit --grep=tag\n\ngroups the \"mentions commit\" and \"mentions tag\" under a new\ntop-level OR node, i.e.\n\n    [all-match]\n    (or\n     (or\n      pattern_body<body>commit\n      pattern_body<body>tag\n     )\n     (or\n      pattern_head<head 1>Linus\n      (or\n       pattern_head<head 0>Junio\n       true\n      )\n     )\n    )\n\nso the top-level backbone \"all-match\" works on becomes\n\n - Mentions either commit or tag,\n - Committed by Linus,\n - Authored by Junio\n\nOne possible improvement we can make is to parse the command line in\nthe last example with \"--all-match\" to\n\n    [all-match]\n    (or\n     pattern_body<body>commit\n     (or\n      pattern_body<body>tag\n      (or\n       pattern_head<head 1>Linus\n       (or\n        pattern_head<head 0>Junio\n        true\n       )\n      )\n     )\n    )\n\nso that the backbone becomes\n\n - Mentions commit,\n - Mentions tag,\n - Committed by Linus,\n - Authored by Junio\n\nto require that both commit and tag are mentioned in the message.\n\n>  t/t7810-grep.sh | 8 ++++++++\n>  1 file changed, 8 insertions(+)\n>\n> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\n> index 1db3dcb..9bc63a3 100755\n> --- a/t/t7810-grep.sh\n> +++ b/t/t7810-grep.sh\n> @@ -580,6 +580,14 @@ test_expect_success 'log with multiple --author uses union' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'log --all-match with multiple --author still uses union' '\n> +\tgit log --all-match --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n> +\t{\n> +\t    echo third && echo second && echo initial\n> +\t} >expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_expect_success 'log with --grep and multiple --author uses all-match' '\n>  \tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n>  \t{\n"},{"id":"198973","messageId":"7vvcfh62l3.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"50518B13.5010702@drmicha.warpmail.net","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-13T21:21:44Z","receivedAt":"2012-09-13T21:21:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> Thanks for \"this\" ;)\n\nHere is a replacement to \"this\", that adds the \"--debug\" option to\n\"git grep\" and an equivalent \"--debug-grep\" to \"git log\" family.\n\n-- >8 --\nSubject: [PATCH] grep: teach --debug option to dump the parse tree\n\nOur \"grep\" allows complex boolean expressions to be formed to match\neach individual line with operators like --and, '(', ')' and --not.\nIntroduce the \"--debug\" option to show the parse tree to help people\nwho want to debug and enhance it.\n\nAlso \"log\" learns \"--debug-grep\" option to do the same.  The command\nline parser to the log family is a lot more limited than the general\n\"git grep\" parser, but it has special handling for header matching\n(e.g. \"--author\"), and a parse tree is valuable when working on it.\n\nNote that \"--all-match\" is *not* any individual node in the parse\ntree.  It is an instruction to the evaluator to check all the nodes\nin the top-level backbone have matched and reject a document as\nnon-matching otherwise.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/grep.c |  3 ++\n grep.c         | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n grep.h         |  1 +\n revision.c     |  2 ++\n 4 files changed, 97 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 09ca4c9..1c6b95a 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -817,6 +817,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t   N_(\"indicate hit with exit status without output\")),\n \t\tOPT_BOOLEAN(0, \"all-match\", &opt.all_match,\n \t\t\tN_(\"show only matches from files that match all patterns\")),\n+\t\t{ OPTION_SET_INT, 0, \"debug\", &opt.debug, NULL,\n+\t\t  N_(\"show parse tree for grep expression\"),\n+\t\t  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },\n \t\tOPT_GROUP(\"\"),\n \t\t{ OPTION_STRING, 'O', \"open-files-in-pager\", &show_in_pager,\n \t\t\tN_(\"pager\"), N_(\"show matching files in the pager\"),\ndiff --git a/grep.c b/grep.c\nindex 04e3ec6..f896d68 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -332,6 +332,87 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)\n \treturn compile_pattern_or(list);\n }\n \n+static void indent(int in)\n+{\n+\twhile (in-- > 0)\n+\t\tfputc(' ', stderr);\n+}\n+\n+static void dump_grep_pat(struct grep_pat *p)\n+{\n+\tswitch (p->token) {\n+\tcase GREP_AND: fprintf(stderr, \"*and*\"); break;\n+\tcase GREP_OPEN_PAREN: fprintf(stderr, \"*(*\"); break;\n+\tcase GREP_CLOSE_PAREN: fprintf(stderr, \"*)*\"); break;\n+\tcase GREP_NOT: fprintf(stderr, \"*not*\"); break;\n+\tcase GREP_OR: fprintf(stderr, \"*or*\"); break;\n+\n+\tcase GREP_PATTERN: fprintf(stderr, \"pattern\"); break;\n+\tcase GREP_PATTERN_HEAD: fprintf(stderr, \"pattern_head\"); break;\n+\tcase GREP_PATTERN_BODY: fprintf(stderr, \"pattern_body\"); break;\n+\t}\n+\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\t\tfprintf(stderr, \"<head %d>\", p->field); break;\n+\tcase GREP_PATTERN_BODY:\n+\t\tfprintf(stderr, \"<body>\"); break;\n+\t}\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\tcase GREP_PATTERN_BODY:\n+\tcase GREP_PATTERN:\n+\t\tfprintf(stderr, \"%.*s\", (int)p->patternlen, p->pattern);\n+\t\tbreak;\n+\t}\n+\tfputc('\\n', stderr);\n+}\n+\n+static void dump_grep_expression_1(struct grep_expr *x, int in)\n+{\n+\tindent(in);\n+\tswitch (x->node) {\n+\tcase GREP_NODE_TRUE:\n+\t\tfprintf(stderr, \"true\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_ATOM:\n+\t\tdump_grep_pat(x->u.atom);\n+\t\tbreak;\n+\tcase GREP_NODE_NOT:\n+\t\tfprintf(stderr, \"(not\\n\");\n+\t\tdump_grep_expression_1(x->u.unary, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_AND:\n+\t\tfprintf(stderr, \"(and\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_OR:\n+\t\tfprintf(stderr, \"(or\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\t}\n+}\n+\n+void dump_grep_expression(struct grep_opt *opt)\n+{\n+\tstruct grep_expr *x = opt->pattern_expression;\n+\n+\tif (opt->all_match)\n+\t\tfprintf(stderr, \"[all-match]\\n\");\n+\tdump_grep_expression_1(x, 0);\n+\tfflush(NULL);\n+}\n+\n static struct grep_expr *grep_true_expr(void)\n {\n \tstruct grep_expr *z = xcalloc(1, sizeof(*z));\n@@ -395,7 +476,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \treturn header_expr;\n }\n \n-void compile_grep_patterns(struct grep_opt *opt)\n+static void compile_grep_patterns_real(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n \tstruct grep_expr *header_expr = prep_header_patterns(opt);\n@@ -415,7 +496,7 @@ void compile_grep_patterns(struct grep_opt *opt)\n \n \tif (opt->all_match || header_expr)\n \t\topt->extended = 1;\n-\telse if (!opt->extended)\n+\telse if (!opt->extended && !opt->debug)\n \t\treturn;\n \n \tp = opt->pattern_list;\n@@ -432,9 +513,17 @@ void compile_grep_patterns(struct grep_opt *opt)\n \telse\n \t\topt->pattern_expression = grep_or_expr(opt->pattern_expression,\n \t\t\t\t\t\t       header_expr);\n+\n \topt->all_match = 1;\n }\n \n+void compile_grep_patterns(struct grep_opt *opt)\n+{\n+\tcompile_grep_patterns_real(opt);\n+\tif (opt->debug)\n+\t\tdump_grep_expression(opt);\n+}\n+\n static void free_pattern_expr(struct grep_expr *x)\n {\n \tswitch (x->node) {\ndiff --git a/grep.h b/grep.h\nindex 75afb7b..00d71f7 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -98,6 +98,7 @@ struct grep_opt {\n \tint word_regexp;\n \tint fixed;\n \tint all_match;\n+\tint debug;\n #define GREP_BINARY_DEFAULT\t0\n #define GREP_BINARY_NOMATCH\t1\n #define GREP_BINARY_TEXT\t2\ndiff --git a/revision.c b/revision.c\nindex dc3fecf..9ef9a4c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1598,6 +1598,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if ((argcount = parse_long_opt(\"grep\", argv, &optarg))) {\n \t\tadd_message_grep(revs, optarg);\n \t\treturn argcount;\n+\t} else if (!strcmp(arg, \"--debug-grep\")) {\n+\t\trevs->grep_filter.debug = 1;\n \t} else if (!strcmp(arg, \"--extended-regexp\") || !strcmp(arg, \"-E\")) {\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n \t} else if (!strcmp(arg, \"--regexp-ignore-case\") || !strcmp(arg, \"-i\")) {\n-- \n1.7.12.469.g5235eb6\n"},{"id":"198982","messageId":"7v7grx5zfq.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"49f89f65cd39306655a9b382a1244e34fb90fff1.1347544259.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv2 6/6] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-13T22:29:45Z","receivedAt":"2012-09-13T22:29:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> The current behavior is probably as useful as it is confusing. In any\n> case it is going to stay. So, document it.\n>\n> This does not take into account the issue of 'log --all-match\n> --author=me --grep=foo --grep=bar' not honoring '--all-match' because it\n> is hopefully a corner case (and, even more hopefully, fixed some time\n> soon).\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n>  Documentation/rev-list-options.txt | 15 ++++++++++++++-\n>  1 file changed, 14 insertions(+), 1 deletion(-)\n>\n> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n> index 5436eba..b2dbfb5 100644\n> --- a/Documentation/rev-list-options.txt\n> +++ b/Documentation/rev-list-options.txt\n> @@ -6,6 +6,19 @@ special notations explained in the description, additional commit\n>  limiting may be applied. Note that they are applied before commit\n>  ordering and formatting options, such as '--reverse'.\n>  \n> +Different options are ANDed: '--author=bar --grep=foo'\n> +limits to commits which match both conditions.\n> +\n> +Several occurences of the '--grep' option are ORed: '--grep=foo --grep=bar'\n> +limits to commits matching any of these conditions.\n> +(If '--all-match' is given, the conditions are ANDed.)\n> +\n> +Several occurences of the '--author' and '--committer' options are ORed\n> +(because there can be only one each per commit).\n\nAs I would really want to eventually see the revision command option\nparser understand the full power of grep expressions in the future,\nI would really want to avoid a misleading explanation that calls\nwhat \"--all-match\" does as \"ANDed\".\n\nWith such a change, we could say something like\n\n\tgit log --grep=commit --and --grep=count\n\nto require the log message to have both \"commit\" and \"count\" on the\nsame line (in any order).  This obviously is different from\n\n\tgit log --grep=\"commit.*count\"\n\nbut more importantly, it is vastly different from\n\n\tgit log --all-match --grep=commit --grep=count\n\nthat requires some line that has \"commit\", and some line (which may\nnot be the same line) that has \"count\", in the log message.\n"},{"id":"198983","messageId":"7vwqzx4i9i.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"7vmx0t7iq0.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 3/6] t7810-grep: test multiple --author with --all-match","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-13T23:26:01Z","receivedAt":"2012-09-13T23:26:01Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> One possible improvement we can make is to parse the command line in\n> the last example with \"--all-match\" to\n>\n>     [all-match]\n>     (or\n>      pattern_body<body>commit\n>      (or\n>       pattern_body<body>tag\n>       (or\n>        pattern_head<head 1>Linus\n>        (or\n>         pattern_head<head 0>Junio\n>         true\n>        )\n>       )\n>      )\n>     )\n>\n> so that the backbone becomes\n>\n>  - Mentions commit,\n>  - Mentions tag,\n>  - Committed by Linus,\n>  - Authored by Junio\n>\n> to require that both commit and tag are mentioned in the message.\n\nAnd this is an attempt to do exactly that.  Earlier, when we have\nboth header expression (which by the way has to be an OR node by\nconstruction) and pattern expression (which could be anything), we\ncreated a top-level OR node (again, look at this as if you are\nreading LISP),\n\n           OR\n        /        \\\n       /          \\\n   pattern            OR\n     / \\           /     \\\n    .....    committer    OR\n                         /   \\ \n                     author   TRUE\n\nin other words, the three elements on the top-level backbone are\n\"pattern\", \"committer\" and \"author\"; when there are more than one\nelements in the \"pattern\", the top-level node of it is OR, so that\nnode is inspected by \"all-match\", hence the result ends up ignoring\nthe \"--all-match\" given from the command line.\n\nThis patch turns it into\n\n\t     OR\n          /      \\\n         /         \\\n        /              OR\n    committer        /    \\\n                 author    \\\n                           pattern\n\nwhen \"--all-match\" was given from the command line, so that the\n\"committer\", \"author\" and elements on the top-level backbone in\n\"pattern\" form the top-level backbone of the resulting expression to\nbe inspected by the \"all-match\" logic.\n\nDoes this pass the expect-failure test in your [PATCH 5/6]?\n\n grep.c | 19 +++++++++++++++++++\n 1 file changed, 19 insertions(+)\n\ndiff --git c/grep.c w/grep.c\nindex be15c47..925aa92 100644\n--- c/grep.c\n+++ w/grep.c\n@@ -476,6 +476,22 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \treturn header_expr;\n }\n \n+static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)\n+{\n+\tstruct grep_expr *z = x;\n+\n+\twhile (x) {\n+\t\tassert(x->node == GREP_NODE_OR);\n+\t\tif (x->u.binary.right &&\n+\t\t    x->u.binary.right->node == GREP_NODE_TRUE) {\n+\t\t\tx->u.binary.right = y;\n+\t\t\tbreak;\n+\t\t}\n+\t\tx = x->u.binary.right;\n+\t}\n+\treturn z;\n+}\n+\n static void compile_grep_patterns_real(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n@@ -510,6 +526,9 @@ static void compile_grep_patterns_real(struct grep_opt *opt)\n \n \tif (!opt->pattern_expression)\n \t\topt->pattern_expression = header_expr;\n+\telse if (opt->all_match)\n+\t\topt->pattern_expression = grep_splice_or(header_expr,\n+\t\t\t\t\t\t\t opt->pattern_expression);\n \telse\n \t\topt->pattern_expression = grep_or_expr(opt->pattern_expression,\n \t\t\t\t\t\t       header_expr);\n"},{"id":"198985","messageId":"7vsjal4d14.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"7v7grx5zfq.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 6/6] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T01:19:03Z","receivedAt":"2012-09-14T01:19:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n>> index 5436eba..b2dbfb5 100644\n>> --- a/Documentation/rev-list-options.txt\n>> +++ b/Documentation/rev-list-options.txt\n>> @@ -6,6 +6,19 @@ special notations explained in the description, additional commit\n>>  limiting may be applied. Note that they are applied before commit\n>>  ordering and formatting options, such as '--reverse'.\n>>  \n>> +Different options are ANDed: '--author=bar --grep=foo'\n>> +limits to commits which match both conditions.\n>> +\n>> +Several occurences of the '--grep' option are ORed: '--grep=foo --grep=bar'\n>> +limits to commits matching any of these conditions.\n>> +(If '--all-match' is given, the conditions are ANDed.)\n>> +\n>> +Several occurences of the '--author' and '--committer' options are ORed\n>> +(because there can be only one each per commit).\n>\n> As I would really want to eventually see the revision command option\n> parser understand the full power of grep expressions in the future,\n> I would really want to avoid a misleading explanation that calls\n> what \"--all-match\" does as \"ANDed\".\n\nAssuming that the patch I posted earlier actually works, I think the\ndescription can become vastly simpler, if you stop explaining author\nand committer in terms of \"grep\".  It is implementation detail that\nthe same grep machinery is handling these two header fields and the\nend users do not have to even be aware of.\n\n\tYou can use \"--grep=foo\" to limit the output to commits that\n\tmention \"foo\" in their messages.  If you use more than one\n\tof them, e.g. \"--grep=foo\" and \"--grep=bar\", by default, the\n\tcommand shows commits that mention \"foo\" or \"bar\" (or\n\tnaturally, both) in their messages.  If you want to limit\n\tthe output to commits that mention both \"foo\" and \"bar\" in\n\ttheir messages (note that they do not have to appear on the\n\tsame line), you can use \"--all-match\".\n\n\tYou can use \"--author=Linus\" to limit the output to commits\n\tauthored by Linus.  If you use more than one of them,\n\te.g. \"--author=Linus\" and \"--author=Junio\", the command\n\tshows commits that are authored by either Linus or Junio.\n\tAs a commit cannot be authored by more than one person,\n\tthere is no option to choose commits that are authored by\n\tLinus and Junio (and there is no need for such an option).\n\tTo limit the output with the committer information, use\n\t\"--committer=<person>\" instead of \"--author=<person>\".\n"},{"id":"198987","messageId":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"7vsjal4d14.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 6/6] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T02:04:17Z","receivedAt":"2012-09-14T02:04:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Assuming that the patch I posted earlier actually works, I think the\n> description can become vastly simpler, if you stop explaining author\n> and committer in terms of \"grep\".\n\nAnd here is a replacement in a patch form.  \n\n-- >8 --\nSubject: [PATCH] log: document use of multiple commit limiting options\n\nGenerally speaking, using more options will further narrow the\nselection, but there are a few exceptions.  Document them.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/rev-list-options.txt | 21 +++++++++++++++++----\n 1 file changed, 17 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 1ae3c89..57d6c90 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -3,7 +3,14 @@ Commit Limiting\n \n Besides specifying a range of commits that should be listed using the\n special notations explained in the description, additional commit\n-limiting may be applied. Note that they are applied before commit\n+limiting may be applied.\n+\n+Using more options generally further limits the output (e.g.\n+\"--since=<date1>\" limits to commits newer than <date1>, and using it\n+with \"--grep=<pattern>\" further limits to commits whose log message\n+has a line that match <pattern>), unless otherwise noted.\n+\n+Note that these are applied before commit\n ordering and formatting options, such as '--reverse'.\n \n --\n@@ -38,16 +45,22 @@ endif::git-rev-list[]\n --committer=<pattern>::\n \n \tLimit the commits output to ones with author/committer\n-\theader lines that match the specified pattern (regular expression).\n+\theader lines that match the specified pattern (regular\n+\texpression).  With more than one `--author=<pattern>`,\n+\tcommits whose author match any of the given patterns are\n+\tchosen (similarly for multiple `--committer=<pattern>`).\n \n --grep=<pattern>::\n \n \tLimit the commits output to ones with log message that\n-\tmatches the specified pattern (regular expression).\n+\tmatches the specified pattern (regular expression).  With\n+\tmore than one `--grep=<pattern>`, commits whose message\n+\tmatch any of the given patterns are chosen (but see\n+\t`--all-match`).\n \n --all-match::\n \tLimit the commits output to ones that match all given --grep,\n-\t--author and --committer instead of ones that match at least one.\n+\tinstead of ones that match at least one.\n \n -i::\n --regexp-ignore-case::\n-- \n1.7.12.469.g5235eb6\n"},{"id":"199004","messageId":"5052E0D8.3040500@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vvcfh62l3.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T07:46:32Z","receivedAt":"2012-09-14T07:46:32Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 13.09.2012 23:21:\n> Michael J Gruber <git@drmicha.warpmail.net> writes:\n> \n>> Thanks for \"this\" ;)\n> \n> Here is a replacement to \"this\", that adds the \"--debug\" option to\n> \"git grep\" and an equivalent \"--debug-grep\" to \"git log\" family.\n> \n> -- >8 --\n> Subject: [PATCH] grep: teach --debug option to dump the parse tree\n> \n> Our \"grep\" allows complex boolean expressions to be formed to match\n> each individual line with operators like --and, '(', ')' and --not.\n> Introduce the \"--debug\" option to show the parse tree to help people\n> who want to debug and enhance it.\n> \n> Also \"log\" learns \"--debug-grep\" option to do the same.  The command\n> line parser to the log family is a lot more limited than the general\n> \"git grep\" parser, but it has special handling for header matching\n> (e.g. \"--author\"), and a parse tree is valuable when working on it.\n> \n> Note that \"--all-match\" is *not* any individual node in the parse\n> tree.  It is an instruction to the evaluator to check all the nodes\n> in the top-level backbone have matched and reject a document as\n> non-matching otherwise.\n\nI haven't read all your responses yet, but the/my main confusion comes\nfrom all-match. My understanding is:\n\n--all-match == turn all top-level ORs into ANDs\n\n(unless it's all --author at the top-level; and I'm referring to user\nsupplied ORs, not those added by the implementation)\n\nSeing (OR foo true) being evaluated to false when foo is false and\nall-match is in effect is terribly confusing, me thinks (debug output).\n\nIn fact, I think the behavior described above (if it's correct) is a\nproduct of the evolution of grep.c and the current implementation\n(turning former unions into intersections in some cases, inserting that\nTRUE node), but not necessarily the intended or preferrable outcome in\nall corner cases.\n\nWe AND different types of limit options in any case (this used to be\naffected by --all-match[?]), and we OR --author options in any case. So\nhaving --all-match turn \"--grep=foo --grep=bar\" from OR into AND would\nmake the most sense at least to me (and I mean: independent of the\npresence of an --author option).\n\nMichael\n"},{"id":"199005","messageId":"5052E1C2.1050008@pobox.com","threadId":"31504","inReplyTo":"5052E0D8.3040500@drmicha.warpmail.net","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T07:50:26Z","receivedAt":"2012-09-14T07:50:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber venit, vidit, dixit 14.09.2012 09:46:\n[snipped, just adding]\n\n...and maybe the meaning of \"(or ...)\" and \"*or*\" isn't what I think it\nis either?\n"},{"id":"199006","messageId":"5052E756.2040605@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vwqzx4i9i.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCHv2 3/6] t7810-grep: test multiple --author with --all-match","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T08:14:14Z","receivedAt":"2012-09-14T08:14:14Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 14.09.2012 01:26:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n>> One possible improvement we can make is to parse the command line in\n>> the last example with \"--all-match\" to\n>>\n>>     [all-match]\n>>     (or\n>>      pattern_body<body>commit\n>>      (or\n>>       pattern_body<body>tag\n>>       (or\n>>        pattern_head<head 1>Linus\n>>        (or\n>>         pattern_head<head 0>Junio\n>>         true\n>>        )\n>>       )\n>>      )\n>>     )\n>>\n>> so that the backbone becomes\n>>\n>>  - Mentions commit,\n>>  - Mentions tag,\n>>  - Committed by Linus,\n>>  - Authored by Junio\n>>\n>> to require that both commit and tag are mentioned in the message.\n> \n> And this is an attempt to do exactly that.  Earlier, when we have\n> both header expression (which by the way has to be an OR node by\n> construction) and pattern expression (which could be anything), we\n> created a top-level OR node (again, look at this as if you are\n> reading LISP),\n> \n>            OR\n>         /        \\\n>        /          \\\n>    pattern            OR\n>      / \\           /     \\\n>     .....    committer    OR\n>                          /   \\ \n>                      author   TRUE\n> \n> in other words, the three elements on the top-level backbone are\n> \"pattern\", \"committer\" and \"author\"; when there are more than one\n> elements in the \"pattern\", the top-level node of it is OR, so that\n> node is inspected by \"all-match\", hence the result ends up ignoring\n> the \"--all-match\" given from the command line.\n> \n> This patch turns it into\n> \n> \t     OR\n>           /      \\\n>          /         \\\n>         /              OR\n>     committer        /    \\\n>                  author    \\\n>                            pattern\n> \n> when \"--all-match\" was given from the command line, so that the\n> \"committer\", \"author\" and elements on the top-level backbone in\n> \"pattern\" form the top-level backbone of the resulting expression to\n> be inspected by the \"all-match\" logic.\n> \n> Does this pass the expect-failure test in your [PATCH 5/6]?\n\nJust a quick heads up:\n\nI merged 38ed8ef (log --grep/--author: honor --all-match honored for\nmultiple --grep patterns, 2012-09-13) from pu into my test branch,\nand this fixes what I had marked as known failure there. Thanks!\n\n[I still have to figure out the logic, but begin to understand that\n\"(OR...) and \"(AND...)\" are linewise, and all-match is a bufferwise AND\nor something. Now, what is \"*or*\" ...]\n\n>  grep.c | 19 +++++++++++++++++++\n>  1 file changed, 19 insertions(+)\n> \n> diff --git c/grep.c w/grep.c\n> index be15c47..925aa92 100644\n> --- c/grep.c\n> +++ w/grep.c\n> @@ -476,6 +476,22 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n>  \treturn header_expr;\n>  }\n>  \n> +static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)\n> +{\n> +\tstruct grep_expr *z = x;\n> +\n> +\twhile (x) {\n> +\t\tassert(x->node == GREP_NODE_OR);\n> +\t\tif (x->u.binary.right &&\n> +\t\t    x->u.binary.right->node == GREP_NODE_TRUE) {\n> +\t\t\tx->u.binary.right = y;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t\tx = x->u.binary.right;\n> +\t}\n> +\treturn z;\n> +}\n> +\n>  static void compile_grep_patterns_real(struct grep_opt *opt)\n>  {\n>  \tstruct grep_pat *p;\n> @@ -510,6 +526,9 @@ static void compile_grep_patterns_real(struct grep_opt *opt)\n>  \n>  \tif (!opt->pattern_expression)\n>  \t\topt->pattern_expression = header_expr;\n> +\telse if (opt->all_match)\n> +\t\topt->pattern_expression = grep_splice_or(header_expr,\n> +\t\t\t\t\t\t\t opt->pattern_expression);\n>  \telse\n>  \t\topt->pattern_expression = grep_or_expr(opt->pattern_expression,\n>  \t\t\t\t\t\t       header_expr);\n> \n"},{"id":"199007","messageId":"5052E8F3.2030305@drmicha.warpmail.net","threadId":"31504","inReplyTo":"5052E1C2.1050008@pobox.com","subject":"Re: [PATCH] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T08:21:07Z","receivedAt":"2012-09-14T08:21:07Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Oh, my gosh, it's not as early as this indicates, rather coffein\ndepletion already:\n\n> Message-ID: <5052E1C2.1050008@pobox.com>\n> Date: Fri, 14 Sep 2012 09:50:26 +0200\n> From: Junio C Hamano <gitster@pobox.com>\n> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120827 Thunderbird/15.0\n\n[no, that Thunderbird user isn't Junio]\n\n> MIME-Version: 1.0\n> To: Michael J Gruber <git@drmicha.warpmail.net>\n> CC: git@vger.kernel.org\n> Subject: Re: [PATCH] rev-list/log: document logic with several limiting options\n\n> Michael J Gruber venit, vidit, dixit 14.09.2012 09:46:\n> [snipped, just adding]\n> \n> ...and maybe the meaning of \"(or ...)\" and \"*or*\" isn't what I think it\n> is either?\n\n[and that confused persion isn't Junio either]\n\nI didn't mean to imposter Junio. Something went wrong with \"virtual\nidentity\" choosing the From: address. Terribly sorry.\n\nMichael (really...)\n"},{"id":"199009","messageId":"cover.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 00/11] rev-list/log: document logic with several limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:32Z","receivedAt":"2012-09-14T09:46:32Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"In v3 I've rebased my tests on top of Junio's commits which change\n--all-match handling and provide a better documentation. Accordingly,\n6/6 from v2 is dropped and 5/5 adjusted (expect_failure -> expect_success).\n\nI'm sending out Junio's commits as in pu along with 3 intermixed fixups which\nyou may squash in freely. (I've only marked the more obvious one as fixup!.)\nThe last 5 are my rebased tests as described above.\n\n[This approach seemed to be more convenient; hopefully for everyone ;)]\n\nJunio C Hamano (3):\n  grep: teach --debug option to dump the parse tree\n  log --grep/--author: honor --all-match honored for multiple --grep\n    patterns\n  log: document use of multiple commit limiting options\n\nMichael J Gruber (8):\n  log: name --debug-grep option like in the commit message\n  grep: show --debug output only once\n  fixup! log: document use of multiple commit limiting options\n  t7810-grep: bring log --grep tests in common form\n  t7810-grep: test multiple --grep with and without --all-match\n  t7810-grep: test multiple --author with --all-match\n  t7810-grep: test interaction of multiple --grep and --author options\n  t7810-grep: test --all-match with multiple --grep and --author\n    options\n\n Documentation/rev-list-options.txt |  23 ++++++--\n builtin/grep.c                     |   4 ++\n grep.c                             | 111 ++++++++++++++++++++++++++++++++++++-\n grep.h                             |   1 +\n revision.c                         |   2 +\n t/t7810-grep.sh                    |  90 +++++++++++++++++++++++++-----\n 6 files changed, 210 insertions(+), 21 deletions(-)\n\n-- \n1.7.12.592.g41e7905\n"},{"id":"199008","messageId":"eb5e7055691692e8a60adf8edbb3b8d2aab9d02b.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 01/11] grep: teach --debug option to dump the parse tree","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:33Z","receivedAt":"2012-09-14T09:46:33Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nOur \"grep\" allows complex boolean expressions to be formed to match\neach individual line with operators like --and, '(', ')' and --not.\nIntroduce the \"--debug\" option to show the parse tree to help people\nwho want to debug and enhance it.\n\nAlso \"log\" learns \"--debug-grep\" option to do the same.  The command\nline parser to the log family is a lot more limited than the general\n\"git grep\" parser, but it has special handling for header matching\n(e.g. \"--author\"), and a parse tree is valuable when working on it.\n\nNote that \"--all-match\" is *not* any individual node in the parse\ntree.  It is an instruction to the evaluator to check all the nodes\nin the top-level backbone have matched and reject a document as\nnon-matching otherwise.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n builtin/grep.c |  3 ++\n grep.c         | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--\n grep.h         |  1 +\n revision.c     |  2 ++\n 4 files changed, 96 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex fe1726f..8aea00c 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -772,6 +772,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t   \"indicate hit with exit status without output\"),\n \t\tOPT_BOOLEAN(0, \"all-match\", &opt.all_match,\n \t\t\t\"show only matches from files that match all patterns\"),\n+\t\t{ OPTION_SET_INT, 0, \"debug\", &opt.debug, NULL,\n+\t\t  \"show parse tree for grep expression\",\n+\t\t  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },\n \t\tOPT_GROUP(\"\"),\n \t\t{ OPTION_STRING, 'O', \"open-files-in-pager\", &show_in_pager,\n \t\t\t\"pager\", \"show matching files in the pager\",\ndiff --git a/grep.c b/grep.c\nindex 04e3ec6..be15c47 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -332,6 +332,87 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)\n \treturn compile_pattern_or(list);\n }\n \n+static void indent(int in)\n+{\n+\twhile (in-- > 0)\n+\t\tfputc(' ', stderr);\n+}\n+\n+static void dump_grep_pat(struct grep_pat *p)\n+{\n+\tswitch (p->token) {\n+\tcase GREP_AND: fprintf(stderr, \"*and*\"); break;\n+\tcase GREP_OPEN_PAREN: fprintf(stderr, \"*(*\"); break;\n+\tcase GREP_CLOSE_PAREN: fprintf(stderr, \"*)*\"); break;\n+\tcase GREP_NOT: fprintf(stderr, \"*not*\"); break;\n+\tcase GREP_OR: fprintf(stderr, \"*or*\"); break;\n+\n+\tcase GREP_PATTERN: fprintf(stderr, \"pattern\"); break;\n+\tcase GREP_PATTERN_HEAD: fprintf(stderr, \"pattern_head\"); break;\n+\tcase GREP_PATTERN_BODY: fprintf(stderr, \"pattern_body\"); break;\n+\t}\n+\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\t\tfprintf(stderr, \"<head %d>\", p->field); break;\n+\tcase GREP_PATTERN_BODY:\n+\t\tfprintf(stderr, \"<body>\"); break;\n+\t}\n+\tswitch (p->token) {\n+\tdefault: break;\n+\tcase GREP_PATTERN_HEAD:\n+\tcase GREP_PATTERN_BODY:\n+\tcase GREP_PATTERN:\n+\t\tfprintf(stderr, \"%.*s\", (int)p->patternlen, p->pattern);\n+\t\tbreak;\n+\t}\n+\tfputc('\\n', stderr);\n+}\n+\n+static void dump_grep_expression_1(struct grep_expr *x, int in)\n+{\n+\tindent(in);\n+\tswitch (x->node) {\n+\tcase GREP_NODE_TRUE:\n+\t\tfprintf(stderr, \"true\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_ATOM:\n+\t\tdump_grep_pat(x->u.atom);\n+\t\tbreak;\n+\tcase GREP_NODE_NOT:\n+\t\tfprintf(stderr, \"(not\\n\");\n+\t\tdump_grep_expression_1(x->u.unary, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_AND:\n+\t\tfprintf(stderr, \"(and\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\tcase GREP_NODE_OR:\n+\t\tfprintf(stderr, \"(or\\n\");\n+\t\tdump_grep_expression_1(x->u.binary.left, in+1);\n+\t\tdump_grep_expression_1(x->u.binary.right, in+1);\n+\t\tindent(in);\n+\t\tfprintf(stderr, \")\\n\");\n+\t\tbreak;\n+\t}\n+}\n+\n+void dump_grep_expression(struct grep_opt *opt)\n+{\n+\tstruct grep_expr *x = opt->pattern_expression;\n+\n+\tif (opt->all_match)\n+\t\tfprintf(stderr, \"[all-match]\\n\");\n+\tdump_grep_expression_1(x, 0);\n+\tfflush(NULL);\n+}\n+\n static struct grep_expr *grep_true_expr(void)\n {\n \tstruct grep_expr *z = xcalloc(1, sizeof(*z));\n@@ -395,7 +476,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \treturn header_expr;\n }\n \n-void compile_grep_patterns(struct grep_opt *opt)\n+static void compile_grep_patterns_real(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n \tstruct grep_expr *header_expr = prep_header_patterns(opt);\n@@ -415,7 +496,7 @@ void compile_grep_patterns(struct grep_opt *opt)\n \n \tif (opt->all_match || header_expr)\n \t\topt->extended = 1;\n-\telse if (!opt->extended)\n+\telse if (!opt->extended && !opt->debug)\n \t\treturn;\n \n \tp = opt->pattern_list;\n@@ -435,6 +516,13 @@ void compile_grep_patterns(struct grep_opt *opt)\n \topt->all_match = 1;\n }\n \n+void compile_grep_patterns(struct grep_opt *opt)\n+{\n+\tcompile_grep_patterns_real(opt);\n+\tif (opt->debug)\n+\t\tdump_grep_expression(opt);\n+}\n+\n static void free_pattern_expr(struct grep_expr *x)\n {\n \tswitch (x->node) {\ndiff --git a/grep.h b/grep.h\nindex ed7de6b..bf5be5a 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -90,6 +90,7 @@ struct grep_opt {\n \tint word_regexp;\n \tint fixed;\n \tint all_match;\n+\tint debug;\n #define GREP_BINARY_DEFAULT\t0\n #define GREP_BINARY_NOMATCH\t1\n #define GREP_BINARY_TEXT\t2\ndiff --git a/revision.c b/revision.c\nindex 9a0d9c7..90376e8 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1578,6 +1578,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if ((argcount = parse_long_opt(\"grep\", argv, &optarg))) {\n \t\tadd_message_grep(revs, optarg);\n \t\treturn argcount;\n+\t} else if (!strcmp(arg, \"--grep-debug\")) {\n+\t\trevs->grep_filter.debug = 1;\n \t} else if (!strcmp(arg, \"--extended-regexp\") || !strcmp(arg, \"-E\")) {\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n \t} else if (!strcmp(arg, \"--regexp-ignore-case\") || !strcmp(arg, \"-i\")) {\n-- \n1.7.12.592.g41e7905\n"},{"id":"199010","messageId":"c9a4c5337142ff53105dfc7346f0fecfbb6bbf30.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 02/11] log: name --debug-grep option like in the commit message","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:34Z","receivedAt":"2012-09-14T09:46:34Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n revision.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/revision.c b/revision.c\nindex 90376e8..fad8040 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1578,7 +1578,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if ((argcount = parse_long_opt(\"grep\", argv, &optarg))) {\n \t\tadd_message_grep(revs, optarg);\n \t\treturn argcount;\n-\t} else if (!strcmp(arg, \"--grep-debug\")) {\n+\t} else if (!strcmp(arg, \"--debug-grep\")) {\n \t\trevs->grep_filter.debug = 1;\n \t} else if (!strcmp(arg, \"--extended-regexp\") || !strcmp(arg, \"-E\")) {\n \t\trevs->grep_filter.regflags |= REG_EXTENDED;\n-- \n1.7.12.592.g41e7905\n"},{"id":"199011","messageId":"53e193b5c4ab329baf469ff20549839fa3088d97.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 03/11] grep: show --debug output only once","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:35Z","receivedAt":"2012-09-14T09:46:35Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"When threaded grep is in effect, the patterns are duplicated and\nrecompiled for each thread. Avoid \"--debug\" output during the\nrecompilation so that the output is given once instead of \"1+nthreads\"\ntimes.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n builtin/grep.c | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 8aea00c..a7e8df0 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -209,6 +209,7 @@ static void start_threads(struct grep_opt *opt)\n \t\tint err;\n \t\tstruct grep_opt *o = grep_opt_dup(opt);\n \t\to->output = strbuf_out;\n+\t\to->debug = 0;\n \t\tcompile_grep_patterns(o);\n \t\terr = pthread_create(&threads[i], NULL, run, o);\n \n-- \n1.7.12.592.g41e7905\n"},{"id":"199019","messageId":"f3240572634fa9e22efd814b1d792d36d56a9643.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 04/11] log --grep/--author: honor --all-match honored for multiple --grep patterns","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:36Z","receivedAt":"2012-09-14T09:46:36Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nEarlier, when we have both header expression (which has to be an OR\nnode by construction) and a pattern expression (which could be\nanything), we created a top-level OR node that looks like this to\nbind them together:\n\n             OR\n        /          \\\n       /            \\\n   pattern            OR\n     / \\           /     \\\n    .....    committer    OR\n                         /   \\\n                     author   TRUE\n\nIn other words, the three elements on the top-level backbone that\nwere inspected by the \"all-match\" logic are \"pattern\", \"committer\"\nand \"author\".  When there are more than one elements in the\n\"pattern\", the top-level node of it is that OR, so that node is\ninspected by \"all-match\", hence the result ends up ignoring the\n\"--all-match\" given from the command line.  A match on either side\nof the pattern was considered a match, hence\n\n        git log --grep=A --grep=B --author=C --all-match\n\nshowed the same \"authored by C and has either A or B\" with or\nwithout --all-match.\n\nThis patch turns the grep expression into this form:\n\n              OR\n          /       \\\n         /          \\\n        /              OR\n    committer        /    \\\n                 author    \\\n                           pattern\n\nwhen \"--all-match\" was given from the command line.  This way, the\nset of nodes on the top-level backbone in the resulting expression\nconsists of \"committer\", \"author\", and whatever nodes were on the\ntop-level backbone of the \"pattern\" expression.  The \"all-match\"\nlogic inspects the same nodes in \"pattern\" as the case without the\nauthor and/or the committer restriction.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n grep.c | 19 +++++++++++++++++++\n 1 file changed, 19 insertions(+)\n\ndiff --git a/grep.c b/grep.c\nindex be15c47..925aa92 100644\n--- a/grep.c\n+++ b/grep.c\n@@ -476,6 +476,22 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)\n \treturn header_expr;\n }\n \n+static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)\n+{\n+\tstruct grep_expr *z = x;\n+\n+\twhile (x) {\n+\t\tassert(x->node == GREP_NODE_OR);\n+\t\tif (x->u.binary.right &&\n+\t\t    x->u.binary.right->node == GREP_NODE_TRUE) {\n+\t\t\tx->u.binary.right = y;\n+\t\t\tbreak;\n+\t\t}\n+\t\tx = x->u.binary.right;\n+\t}\n+\treturn z;\n+}\n+\n static void compile_grep_patterns_real(struct grep_opt *opt)\n {\n \tstruct grep_pat *p;\n@@ -510,6 +526,9 @@ static void compile_grep_patterns_real(struct grep_opt *opt)\n \n \tif (!opt->pattern_expression)\n \t\topt->pattern_expression = header_expr;\n+\telse if (opt->all_match)\n+\t\topt->pattern_expression = grep_splice_or(header_expr,\n+\t\t\t\t\t\t\t opt->pattern_expression);\n \telse\n \t\topt->pattern_expression = grep_or_expr(opt->pattern_expression,\n \t\t\t\t\t\t       header_expr);\n-- \n1.7.12.592.g41e7905\n"},{"id":"199014","messageId":"b7958362b037c298344a03f2657456b3809c3239.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 05/11] log: document use of multiple commit limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:37Z","receivedAt":"2012-09-14T09:46:37Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nGenerally speaking, using more options will further narrow the\nselection, but there are a few exceptions.  Document them.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n Documentation/rev-list-options.txt | 21 +++++++++++++++++----\n 1 file changed, 17 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 1ae3c89..57d6c90 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -3,7 +3,14 @@ Commit Limiting\n \n Besides specifying a range of commits that should be listed using the\n special notations explained in the description, additional commit\n-limiting may be applied. Note that they are applied before commit\n+limiting may be applied.\n+\n+Using more options generally further limits the output (e.g.\n+\"--since=<date1>\" limits to commits newer than <date1>, and using it\n+with \"--grep=<pattern>\" further limits to commits whose log message\n+has a line that match <pattern>), unless otherwise noted.\n+\n+Note that these are applied before commit\n ordering and formatting options, such as '--reverse'.\n \n --\n@@ -38,16 +45,22 @@ endif::git-rev-list[]\n --committer=<pattern>::\n \n \tLimit the commits output to ones with author/committer\n-\theader lines that match the specified pattern (regular expression).\n+\theader lines that match the specified pattern (regular\n+\texpression).  With more than one `--author=<pattern>`,\n+\tcommits whose author match any of the given patterns are\n+\tchosen (similarly for multiple `--committer=<pattern>`).\n \n --grep=<pattern>::\n \n \tLimit the commits output to ones with log message that\n-\tmatches the specified pattern (regular expression).\n+\tmatches the specified pattern (regular expression).  With\n+\tmore than one `--grep=<pattern>`, commits whose message\n+\tmatch any of the given patterns are chosen (but see\n+\t`--all-match`).\n \n --all-match::\n \tLimit the commits output to ones that match all given --grep,\n-\t--author and --committer instead of ones that match at least one.\n+\tinstead of ones that match at least one.\n \n -i::\n --regexp-ignore-case::\n-- \n1.7.12.592.g41e7905\n"},{"id":"199012","messageId":"a22139a2cd54d1fa1b5bebc447540f7c54bf305a.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 06/11] fixup! log: document use of multiple commit limiting options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:38Z","receivedAt":"2012-09-14T09:46:38Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Here are a few typo fixes.\n\nThere is a mix of single and back ticks already before this patch,\ni.e. ` vs. ' -- I thought we had guidelines for this but don't find them\nat the moment.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n Documentation/rev-list-options.txt | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 57d6c90..c828408 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -6,12 +6,12 @@ special notations explained in the description, additional commit\n limiting may be applied.\n \n Using more options generally further limits the output (e.g.\n-\"--since=<date1>\" limits to commits newer than <date1>, and using it\n-with \"--grep=<pattern>\" further limits to commits whose log message\n-has a line that match <pattern>), unless otherwise noted.\n+`--since=<date1>` limits to commits newer than `<date1>`, and using it\n+with `--grep=<pattern>` further limits to commits whose log message\n+has a line that matches `<pattern>`), unless otherwise noted.\n \n Note that these are applied before commit\n-ordering and formatting options, such as '--reverse'.\n+ordering and formatting options, such as `--reverse`.\n \n --\n \n@@ -47,7 +47,7 @@ endif::git-rev-list[]\n \tLimit the commits output to ones with author/committer\n \theader lines that match the specified pattern (regular\n \texpression).  With more than one `--author=<pattern>`,\n-\tcommits whose author match any of the given patterns are\n+\tcommits whose author matches any of the given patterns are\n \tchosen (similarly for multiple `--committer=<pattern>`).\n \n --grep=<pattern>::\n@@ -55,7 +55,7 @@ endif::git-rev-list[]\n \tLimit the commits output to ones with log message that\n \tmatches the specified pattern (regular expression).  With\n \tmore than one `--grep=<pattern>`, commits whose message\n-\tmatch any of the given patterns are chosen (but see\n+\tmatches any of the given patterns are chosen (but see\n \t`--all-match`).\n \n --all-match::\n-- \n1.7.12.592.g41e7905\n"},{"id":"199018","messageId":"83691edd7d999104649b311b98acfe5b782415f3.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 07/11] t7810-grep: bring log --grep tests in common form","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:39Z","receivedAt":"2012-09-14T09:46:39Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"The log --grep tests generate the expected out in different ways.\nMake them all use command blocks so that subshells are avoided and the\nexpected output is easier to grasp visually.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 24 ++++++++++++++++++------\n 1 file changed, 18 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 24e9b19..180e998 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -435,31 +435,41 @@ test_expect_success 'log grep setup' '\n \n test_expect_success 'log grep (1)' '\n \tgit log --author=author --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (2)' '\n \tgit log --author=\" * \" -F --pretty=tformat:%s >actual &&\n-\t( echo second ) >expect &&\n+\t{\n+\t\techo second\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (3)' '\n \tgit log --author=\"^A U\" --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (4)' '\n \tgit log --author=\"frotz\\.com>$\" --pretty=tformat:%s >actual &&\n-\t( echo second ) >expect &&\n+\t{\n+\t\techo second\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'log grep (5)' '\n \tgit log --author=Thor -F --pretty=tformat:%s >actual &&\n-\t( echo third ; echo initial ) >expect &&\n+\t{\n+\t\techo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n@@ -473,7 +483,9 @@ test_expect_success 'log --grep --author implicitly uses all-match' '\n \t# grep matches initial and second but not third\n \t# author matches only initial and third\n \tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n-\techo initial >expect &&\n+\t{\n+\t\techo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n1.7.12.592.g41e7905\n"},{"id":"199013","messageId":"04dd784c3a4a5bce6463ee0aaf3130f6e822ba2f.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 08/11] t7810-grep: test multiple --grep with and without --all-match","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:40Z","receivedAt":"2012-09-14T09:46:40Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 16 ++++++++++++++++\n 1 file changed, 16 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 180e998..b841909 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -479,6 +479,22 @@ test_expect_success 'log grep (6)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log with multiple --grep uses union' '\n+\tgit log --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo fourth && echo third && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --all-match with multiple --grep uses intersection' '\n+\tgit log --all-match --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo third\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log --grep --author implicitly uses all-match' '\n \t# grep matches initial and second but not third\n \t# author matches only initial and third\n-- \n1.7.12.592.g41e7905\n"},{"id":"199017","messageId":"830d4a80bb229835b6b4898c3c4b8b2e0e17b056.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 09/11] t7810-grep: test multiple --author with --all-match","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:41Z","receivedAt":"2012-09-14T09:46:41Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"--all-match is ignored for author matching on purpose.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 8 ++++++++\n 1 file changed, 8 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex b841909..be81d96 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -513,6 +513,14 @@ test_expect_success 'log with multiple --author uses union' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --all-match with multiple --author still uses union' '\n+\tgit log --all-match --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n+\t{\n+\t    echo third && echo second && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log with --grep and multiple --author uses all-match' '\n \tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n \t{\n-- \n1.7.12.592.g41e7905\n"},{"id":"199015","messageId":"e55a91f36d1accfb94fac34aba9ca1eade7b6777.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 10/11] t7810-grep: test interaction of multiple --grep and --author options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:42Z","receivedAt":"2012-09-14T09:46:42Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"There are tests for this interaction already. Restructure slightly and\navoid any claims about --all-match.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 38 ++++++++++++++++++++++----------------\n 1 file changed, 22 insertions(+), 16 deletions(-)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex be81d96..f6edb4d 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -495,16 +495,6 @@ test_expect_success 'log --all-match with multiple --grep uses intersection' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log --grep --author implicitly uses all-match' '\n-\t# grep matches initial and second but not third\n-\t# author matches only initial and third\n-\tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n-\t{\n-\t\techo initial\n-\t} >expect &&\n-\ttest_cmp expect actual\n-'\n-\n test_expect_success 'log with multiple --author uses union' '\n \tgit log --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n \t{\n@@ -521,17 +511,33 @@ test_expect_success 'log --all-match with multiple --author still uses union' '\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log with --grep and multiple --author uses all-match' '\n-\tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+test_expect_success 'log --grep --author uses intersection' '\n+\t# grep matches only third and fourth\n+\t# author matches only initial and third\n+\tgit log --author=\"A U Thor\" --grep=r --format=%s >actual &&\n \t{\n-\t    echo third && echo initial\n+\t\techo third\n \t} >expect &&\n \ttest_cmp expect actual\n '\n \n-test_expect_success 'log with --grep and multiple --author uses all-match' '\n-\tgit log --author=\"Thor\" --author=\"Night\" --grep=q --format=%s >actual &&\n-\t>expect &&\n+test_expect_success 'log --grep --grep --author takes union of greps and intersects with author' '\n+\t# grep matches initial and second but not third\n+\t# author matches only initial and third\n+\tgit log --author=\"A U Thor\" --grep=s --grep=l --format=%s >actual &&\n+\t{\n+\t\techo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '\n+\t# grep matches only initial and third\n+\t# author matches all but second\n+\tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+\t{\n+\t    echo third && echo initial\n+\t} >expect &&\n \ttest_cmp expect actual\n '\n \n-- \n1.7.12.592.g41e7905\n"},{"id":"199016","messageId":"155f30ede8a788c599189af677936b15fabf041b.1347615361.git.git@drmicha.warpmail.net","threadId":"31504","inReplyTo":"7vfw6l9x7i.fsf@alter.siamese.dyndns.org","subject":"[PATCHv3 11/11] t7810-grep: test --all-match with multiple --grep and --author options","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2012-09-14T09:46:43Z","receivedAt":"2012-09-14T09:46:43Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"--all-match is ignored with multiple author options on purpose but\nrequires all --grep to be matched on some line.\n\nSigned-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n---\n t/t7810-grep.sh | 20 ++++++++++++++++++++\n 1 file changed, 20 insertions(+)\n\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex f6edb4d..b5c488e 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -531,6 +531,16 @@ test_expect_success 'log --grep --grep --author takes union of greps and interse\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log ---all-match -grep --author --author still takes union of authors and intersects with grep' '\n+\t# grep matches only initial and third\n+\t# author matches all but second\n+\tgit log --all-match --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n+\t{\n+\t    echo third && echo initial\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '\n \t# grep matches only initial and third\n \t# author matches all but second\n@@ -541,6 +551,16 @@ test_expect_success 'log --grep --author --author takes union of authors and int\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --all-match --grep --grep --author takes intersection' '\n+\t# grep matches only third\n+\t# author matches only initial and third\n+\tgit log --all-match --author=\"A U Thor\" --grep=i --grep=r --format=%s >actual &&\n+\t{\n+\t\techo third\n+\t} >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'grep with CE_VALID file' '\n \tgit update-index --assume-unchanged t/t &&\n \trm t/t &&\n-- \n1.7.12.592.g41e7905\n"},{"id":"199038","messageId":"7vboh87g5k.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"5052E756.2040605@drmicha.warpmail.net","subject":"Re: [PATCHv2 3/6] t7810-grep: test multiple --author with --all-match","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T15:55:35Z","receivedAt":"2012-09-14T15:55:35Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> Junio C Hamano venit, vidit, dixit 14.09.2012 01:26:\n> ...\n>> when \"--all-match\" was given from the command line, so that the\n>> \"committer\", \"author\" and elements on the top-level backbone in\n>> \"pattern\" form the top-level backbone of the resulting expression to\n>> be inspected by the \"all-match\" logic.\n>> \n>> Does this pass the expect-failure test in your [PATCH 5/6]?\n>\n> Just a quick heads up:\n>\n> I merged 38ed8ef (log --grep/--author: honor --all-match honored for\n> multiple --grep patterns, 2012-09-13) from pu into my test branch,\n> and this fixes what I had marked as known failure there. Thanks!\n\nThanks for testing.\n\n>\n> I still have to figure out the logic, but begin to understand that\n> \"(OR...) and \"(AND...)\" are linewise, and all-match is a bufferwise AND\n\nYes, all-match is about requiring all the top-level nodes to have\nfired while inspecting the whole file.  So between these:\n\n    $ git grep -e foo --and -e bar\n    $ git grep --all-match -e foo -e bar\n\nthe former shows lines that has both foo and bar, while the latter\nshows lines that has either foo or bar but only from files that has\nboth in them (on possibly separate lines).\n\n> Now, what is \"*or*\" ...\n\nThat is for to show the token we received from the command line\nparser; the more interesting part is the parsed expression tree,\nthat is mostly formed as a tree with each node labeled with what\nkind of operation it represents.\n"},{"id":"199047","messageId":"7vr4q45y65.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"eb5e7055691692e8a60adf8edbb3b8d2aab9d02b.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 01/11] grep: teach --debug option to dump the parse tree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T17:09:22Z","receivedAt":"2012-09-14T17:09:22Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> From: Junio C Hamano <gitster@pobox.com>\n>\n> Our \"grep\" allows complex boolean expressions to be formed to match\n> each individual line with operators like --and, '(', ')' and --not.\n> Introduce the \"--debug\" option to show the parse tree to help people\n> who want to debug and enhance it.\n>\n> Also \"log\" learns \"--debug-grep\" option to do the same.  The command\n\nThis was actually a leftover incorrect message.\n\nWhen we introduce the equivalent of\n\n    $ git grep -e foo --and --not \\( -e bar -e baz \\)\n\nto the log family in some distant future, we may end up having to\ndisambiguate the \"--not\" (which means something completely different\nfor the log family) meant for the grep part by doing\n\n    $ git log --grep=foo --grep-and --grep-not \\\n    \t--grep-\\( --grep=bar --grep=baz --grep-\\)\n\nor something like that, and the code says --grep-debug because that\nwould fit better than --debug-grep.\n\nOther than that, the patch looks good ;-)\n"},{"id":"199048","messageId":"7vmx0s5y1x.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"53e193b5c4ab329baf469ff20549839fa3088d97.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 03/11] grep: show --debug output only once","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T17:11:54Z","receivedAt":"2012-09-14T17:11:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> When threaded grep is in effect, the patterns are duplicated and\n> recompiled for each thread. Avoid \"--debug\" output during the\n> recompilation so that the output is given once instead of \"1+nthreads\"\n> times.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n>  builtin/grep.c | 1 +\n>  1 file changed, 1 insertion(+)\n>\n> diff --git a/builtin/grep.c b/builtin/grep.c\n> index 8aea00c..a7e8df0 100644\n> --- a/builtin/grep.c\n> +++ b/builtin/grep.c\n> @@ -209,6 +209,7 @@ static void start_threads(struct grep_opt *opt)\n>  \t\tint err;\n>  \t\tstruct grep_opt *o = grep_opt_dup(opt);\n>  \t\to->output = strbuf_out;\n> +\t\to->debug = 0;\n>  \t\tcompile_grep_patterns(o);\n>  \t\terr = pthread_create(&threads[i], NULL, run, o);\n\nMakes sense; thanks.\n"},{"id":"199052","messageId":"7vipbg5xin.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"a22139a2cd54d1fa1b5bebc447540f7c54bf305a.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 06/11] fixup! log: document use of multiple commit limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T17:23:28Z","receivedAt":"2012-09-14T17:23:28Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> Here are a few typo fixes.\n>\n> There is a mix of single and back ticks already before this patch,\n> i.e. ` vs. ' -- I thought we had guidelines for this but don't find them\n> at the moment.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n>  Documentation/rev-list-options.txt | 12 ++++++------\n>  1 file changed, 6 insertions(+), 6 deletions(-)\n\nThanks, will squash in.\n\nIn general:\n\n - we want to use `exactly this` when writing an item that the user\n   has to exactly spell as in the text, e.g. subcommand names.\n\n - from the older days, we use <angle bracket as placeholder> in\n   synopsis section and in \"git subcmd -h\" output, and in the body\n   text, we tend to write like '<this>' to italicise in the\n   documentation.\n\nI personally find the <angle> somewhat ugly in the documentation,\nbut we cannot just drop them as the \"man -Tascii\" would suffer if we\ndid so.\n\n>\n> diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\n> index 57d6c90..c828408 100644\n> --- a/Documentation/rev-list-options.txt\n> +++ b/Documentation/rev-list-options.txt\n> @@ -6,12 +6,12 @@ special notations explained in the description, additional commit\n>  limiting may be applied.\n>  \n>  Using more options generally further limits the output (e.g.\n> -\"--since=<date1>\" limits to commits newer than <date1>, and using it\n> -with \"--grep=<pattern>\" further limits to commits whose log message\n> -has a line that match <pattern>), unless otherwise noted.\n> +`--since=<date1>` limits to commits newer than `<date1>`, and using it\n> +with `--grep=<pattern>` further limits to commits whose log message\n> +has a line that matches `<pattern>`), unless otherwise noted.\n>  \n>  Note that these are applied before commit\n> -ordering and formatting options, such as '--reverse'.\n> +ordering and formatting options, such as `--reverse`.\n>  \n>  --\n>  \n> @@ -47,7 +47,7 @@ endif::git-rev-list[]\n>  \tLimit the commits output to ones with author/committer\n>  \theader lines that match the specified pattern (regular\n>  \texpression).  With more than one `--author=<pattern>`,\n> -\tcommits whose author match any of the given patterns are\n> +\tcommits whose author matches any of the given patterns are\n>  \tchosen (similarly for multiple `--committer=<pattern>`).\n>  \n>  --grep=<pattern>::\n> @@ -55,7 +55,7 @@ endif::git-rev-list[]\n>  \tLimit the commits output to ones with log message that\n>  \tmatches the specified pattern (regular expression).  With\n>  \tmore than one `--grep=<pattern>`, commits whose message\n> -\tmatch any of the given patterns are chosen (but see\n> +\tmatches any of the given patterns are chosen (but see\n>  \t`--all-match`).\n>  \n>  --all-match::\n"},{"id":"199053","messageId":"7vehm45xfz.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"cover.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 00/11] rev-list/log: document logic with several limiting options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T17:25:04Z","receivedAt":"2012-09-14T17:25:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks for an update.  Queued with minimum modification.\n"},{"id":"199061","messageId":"7vy5kc4hb7.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"830d4a80bb229835b6b4898c3c4b8b2e0e17b056.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 09/11] t7810-grep: test multiple --author with --all-match","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T17:58:52Z","receivedAt":"2012-09-14T17:58:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> --all-match is ignored for author matching on purpose.\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n\nIt is more like \"--all-match is about --grep and does not interact\nwith --author or --committer at all\".  At least with the recent fix.\n\n\n>  t/t7810-grep.sh | 8 ++++++++\n>  1 file changed, 8 insertions(+)\n>\n> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\n> index b841909..be81d96 100755\n> --- a/t/t7810-grep.sh\n> +++ b/t/t7810-grep.sh\n> @@ -513,6 +513,14 @@ test_expect_success 'log with multiple --author uses union' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'log --all-match with multiple --author still uses union' '\n> +\tgit log --all-match --author=\"Thor\" --author=\"Aster\" --format=%s >actual &&\n> +\t{\n> +\t    echo third && echo second && echo initial\n> +\t} >expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_expect_success 'log with --grep and multiple --author uses all-match' '\n>  \tgit log --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n>  \t{\n"},{"id":"199062","messageId":"7vtxv04h7e.fsf@alter.siamese.dyndns.org","threadId":"31504","inReplyTo":"155f30ede8a788c599189af677936b15fabf041b.1347615361.git.git@drmicha.warpmail.net","subject":"Re: [PATCHv3 11/11] t7810-grep: test --all-match with multiple --grep and --author options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-09-14T18:01:09Z","receivedAt":"2012-09-14T18:01:09Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> --all-match is ignored with multiple author options on purpose but\n> requires all --grep to be matched on some line.\n\nIt is more like \"the behaviour of --all-match to tie more than one --grep\nused to be broken when --author or --committer is used\".\n\n>\n> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>\n> ---\n>  t/t7810-grep.sh | 20 ++++++++++++++++++++\n>  1 file changed, 20 insertions(+)\n>\n> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\n> index f6edb4d..b5c488e 100755\n> --- a/t/t7810-grep.sh\n> +++ b/t/t7810-grep.sh\n> @@ -531,6 +531,16 @@ test_expect_success 'log --grep --grep --author takes union of greps and interse\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'log ---all-match -grep --author --author still takes union of authors and intersects with grep' '\n> +\t# grep matches only initial and third\n> +\t# author matches all but second\n> +\tgit log --all-match --author=\"Thor\" --author=\"Night\" --grep=i --format=%s >actual &&\n> +\t{\n> +\t    echo third && echo initial\n> +\t} >expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_expect_success 'log --grep --author --author takes union of authors and intersects with grep' '\n>  \t# grep matches only initial and third\n>  \t# author matches all but second\n> @@ -541,6 +551,16 @@ test_expect_success 'log --grep --author --author takes union of authors and int\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'log --all-match --grep --grep --author takes intersection' '\n> +\t# grep matches only third\n> +\t# author matches only initial and third\n> +\tgit log --all-match --author=\"A U Thor\" --grep=i --grep=r --format=%s >actual &&\n> +\t{\n> +\t\techo third\n> +\t} >expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_expect_success 'grep with CE_VALID file' '\n>  \tgit update-index --assume-unchanged t/t &&\n>  \trm t/t &&\n"}]}