Skip to content

Commit 31d69db

Browse files
committed
Merge branch 'jc/maint-log-grep-all-match-1' into maint
* jc/maint-log-grep-all-match-1: grep.c: make two symbols really file-scope static this time t7810-grep: test --all-match with multiple --grep and --author options t7810-grep: test interaction of multiple --grep and --author options t7810-grep: test multiple --author with --all-match t7810-grep: test multiple --grep with and without --all-match t7810-grep: bring log --grep tests in common form grep.c: mark private file-scope symbols as static log: document use of multiple commit limiting options log --grep/--author: honor --all-match honored for multiple --grep patterns grep: show --debug output only once grep: teach --debug option to dump the parse tree
2 parents 52938b1 + 3083301 commit 31d69db

File tree

6 files changed

+217
-25
lines changed

6 files changed

+217
-25
lines changed

Documentation/rev-list-options.txt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ Commit Limiting
33

44
Besides specifying a range of commits that should be listed using the
55
special notations explained in the description, additional commit
6-
limiting may be applied. Note that they are applied before commit
7-
ordering and formatting options, such as '--reverse'.
6+
limiting may be applied.
7+
8+
Using more options generally further limits the output (e.g.
9+
`--since=<date1>` limits to commits newer than `<date1>`, and using it
10+
with `--grep=<pattern>` further limits to commits whose log message
11+
has a line that matches `<pattern>`), unless otherwise noted.
12+
13+
Note that these are applied before commit
14+
ordering and formatting options, such as `--reverse`.
815

916
--
1017

@@ -39,16 +46,22 @@ endif::git-rev-list[]
3946
--committer=<pattern>::
4047

4148
Limit the commits output to ones with author/committer
42-
header lines that match the specified pattern (regular expression).
49+
header lines that match the specified pattern (regular
50+
expression). With more than one `--author=<pattern>`,
51+
commits whose author matches any of the given patterns are
52+
chosen (similarly for multiple `--committer=<pattern>`).
4353

4454
--grep=<pattern>::
4555

4656
Limit the commits output to ones with log message that
47-
matches the specified pattern (regular expression).
57+
matches the specified pattern (regular expression). With
58+
more than one `--grep=<pattern>`, commits whose message
59+
matches any of the given patterns are chosen (but see
60+
`--all-match`).
4861

4962
--all-match::
5063
Limit the commits output to ones that match all given --grep,
51-
--author and --committer instead of ones that match at least one.
64+
instead of ones that match at least one.
5265

5366
-i::
5467
--regexp-ignore-case::

builtin/grep.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ static void start_threads(struct grep_opt *opt)
209209
int err;
210210
struct grep_opt *o = grep_opt_dup(opt);
211211
o->output = strbuf_out;
212+
o->debug = 0;
212213
compile_grep_patterns(o);
213214
err = pthread_create(&threads[i], NULL, run, o);
214215

@@ -772,6 +773,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
772773
"indicate hit with exit status without output"),
773774
OPT_BOOLEAN(0, "all-match", &opt.all_match,
774775
"show only matches from files that match all patterns"),
776+
{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
777+
"show parse tree for grep expression",
778+
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
775779
OPT_GROUP(""),
776780
{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
777781
"pager", "show matching files in the pager",

grep.c

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#include "userdiff.h"
44
#include "xdiff-interface.h"
55

6+
static int grep_source_load(struct grep_source *gs);
7+
static int grep_source_is_binary(struct grep_source *gs);
8+
9+
610
static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
711
const char *origin, int no,
812
enum grep_pat_token t,
@@ -332,6 +336,87 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
332336
return compile_pattern_or(list);
333337
}
334338

339+
static void indent(int in)
340+
{
341+
while (in-- > 0)
342+
fputc(' ', stderr);
343+
}
344+
345+
static void dump_grep_pat(struct grep_pat *p)
346+
{
347+
switch (p->token) {
348+
case GREP_AND: fprintf(stderr, "*and*"); break;
349+
case GREP_OPEN_PAREN: fprintf(stderr, "*(*"); break;
350+
case GREP_CLOSE_PAREN: fprintf(stderr, "*)*"); break;
351+
case GREP_NOT: fprintf(stderr, "*not*"); break;
352+
case GREP_OR: fprintf(stderr, "*or*"); break;
353+
354+
case GREP_PATTERN: fprintf(stderr, "pattern"); break;
355+
case GREP_PATTERN_HEAD: fprintf(stderr, "pattern_head"); break;
356+
case GREP_PATTERN_BODY: fprintf(stderr, "pattern_body"); break;
357+
}
358+
359+
switch (p->token) {
360+
default: break;
361+
case GREP_PATTERN_HEAD:
362+
fprintf(stderr, "<head %d>", p->field); break;
363+
case GREP_PATTERN_BODY:
364+
fprintf(stderr, "<body>"); break;
365+
}
366+
switch (p->token) {
367+
default: break;
368+
case GREP_PATTERN_HEAD:
369+
case GREP_PATTERN_BODY:
370+
case GREP_PATTERN:
371+
fprintf(stderr, "%.*s", (int)p->patternlen, p->pattern);
372+
break;
373+
}
374+
fputc('\n', stderr);
375+
}
376+
377+
static void dump_grep_expression_1(struct grep_expr *x, int in)
378+
{
379+
indent(in);
380+
switch (x->node) {
381+
case GREP_NODE_TRUE:
382+
fprintf(stderr, "true\n");
383+
break;
384+
case GREP_NODE_ATOM:
385+
dump_grep_pat(x->u.atom);
386+
break;
387+
case GREP_NODE_NOT:
388+
fprintf(stderr, "(not\n");
389+
dump_grep_expression_1(x->u.unary, in+1);
390+
indent(in);
391+
fprintf(stderr, ")\n");
392+
break;
393+
case GREP_NODE_AND:
394+
fprintf(stderr, "(and\n");
395+
dump_grep_expression_1(x->u.binary.left, in+1);
396+
dump_grep_expression_1(x->u.binary.right, in+1);
397+
indent(in);
398+
fprintf(stderr, ")\n");
399+
break;
400+
case GREP_NODE_OR:
401+
fprintf(stderr, "(or\n");
402+
dump_grep_expression_1(x->u.binary.left, in+1);
403+
dump_grep_expression_1(x->u.binary.right, in+1);
404+
indent(in);
405+
fprintf(stderr, ")\n");
406+
break;
407+
}
408+
}
409+
410+
static void dump_grep_expression(struct grep_opt *opt)
411+
{
412+
struct grep_expr *x = opt->pattern_expression;
413+
414+
if (opt->all_match)
415+
fprintf(stderr, "[all-match]\n");
416+
dump_grep_expression_1(x, 0);
417+
fflush(NULL);
418+
}
419+
335420
static struct grep_expr *grep_true_expr(void)
336421
{
337422
struct grep_expr *z = xcalloc(1, sizeof(*z));
@@ -395,7 +480,23 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
395480
return header_expr;
396481
}
397482

398-
void compile_grep_patterns(struct grep_opt *opt)
483+
static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)
484+
{
485+
struct grep_expr *z = x;
486+
487+
while (x) {
488+
assert(x->node == GREP_NODE_OR);
489+
if (x->u.binary.right &&
490+
x->u.binary.right->node == GREP_NODE_TRUE) {
491+
x->u.binary.right = y;
492+
break;
493+
}
494+
x = x->u.binary.right;
495+
}
496+
return z;
497+
}
498+
499+
static void compile_grep_patterns_real(struct grep_opt *opt)
399500
{
400501
struct grep_pat *p;
401502
struct grep_expr *header_expr = prep_header_patterns(opt);
@@ -415,7 +516,7 @@ void compile_grep_patterns(struct grep_opt *opt)
415516

416517
if (opt->all_match || header_expr)
417518
opt->extended = 1;
418-
else if (!opt->extended)
519+
else if (!opt->extended && !opt->debug)
419520
return;
420521

421522
p = opt->pattern_list;
@@ -429,12 +530,22 @@ void compile_grep_patterns(struct grep_opt *opt)
429530

430531
if (!opt->pattern_expression)
431532
opt->pattern_expression = header_expr;
533+
else if (opt->all_match)
534+
opt->pattern_expression = grep_splice_or(header_expr,
535+
opt->pattern_expression);
432536
else
433537
opt->pattern_expression = grep_or_expr(opt->pattern_expression,
434538
header_expr);
435539
opt->all_match = 1;
436540
}
437541

542+
void compile_grep_patterns(struct grep_opt *opt)
543+
{
544+
compile_grep_patterns_real(opt);
545+
if (opt->debug)
546+
dump_grep_expression(opt);
547+
}
548+
438549
static void free_pattern_expr(struct grep_expr *x)
439550
{
440551
switch (x->node) {
@@ -1358,7 +1469,7 @@ static int grep_source_load_file(struct grep_source *gs)
13581469
return 0;
13591470
}
13601471

1361-
int grep_source_load(struct grep_source *gs)
1472+
static int grep_source_load(struct grep_source *gs)
13621473
{
13631474
if (gs->buf)
13641475
return 0;
@@ -1386,7 +1497,7 @@ void grep_source_load_driver(struct grep_source *gs)
13861497
grep_attr_unlock();
13871498
}
13881499

1389-
int grep_source_is_binary(struct grep_source *gs)
1500+
static int grep_source_is_binary(struct grep_source *gs)
13901501
{
13911502
grep_source_load_driver(gs);
13921503
if (gs->driver->binary != -1)

grep.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct grep_opt {
9090
int word_regexp;
9191
int fixed;
9292
int all_match;
93+
int debug;
9394
#define GREP_BINARY_DEFAULT 0
9495
#define GREP_BINARY_NOMATCH 1
9596
#define GREP_BINARY_TEXT 2
@@ -148,11 +149,10 @@ struct grep_source {
148149

149150
void grep_source_init(struct grep_source *gs, enum grep_source_type type,
150151
const char *name, const void *identifier);
151-
int grep_source_load(struct grep_source *gs);
152152
void grep_source_clear_data(struct grep_source *gs);
153153
void grep_source_clear(struct grep_source *gs);
154154
void grep_source_load_driver(struct grep_source *gs);
155-
int grep_source_is_binary(struct grep_source *gs);
155+
156156

157157
int grep_source(struct grep_opt *opt, struct grep_source *gs);
158158

revision.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
15981598
} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
15991599
add_message_grep(revs, optarg);
16001600
return argcount;
1601+
} else if (!strcmp(arg, "--grep-debug")) {
1602+
revs->grep_filter.debug = 1;
16011603
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
16021604
revs->grep_filter.regflags |= REG_EXTENDED;
16031605
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {

0 commit comments

Comments
 (0)