Skip to content

Commit

Permalink
Merge branch 'jc/maint-log-grep-all-match-1' into maint
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
gitster committed Sep 30, 2012
2 parents 52938b1 + 3083301 commit 31d69db
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 25 deletions.
23 changes: 18 additions & 5 deletions Documentation/rev-list-options.txt
Expand Up @@ -3,8 +3,15 @@ Commit Limiting


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

Note that these are applied before commit
ordering and formatting options, such as `--reverse`.


-- --


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


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


--grep=<pattern>:: --grep=<pattern>::


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


--all-match:: --all-match::
Limit the commits output to ones that match all given --grep, Limit the commits output to ones that match all given --grep,
--author and --committer instead of ones that match at least one. instead of ones that match at least one.


-i:: -i::
--regexp-ignore-case:: --regexp-ignore-case::
Expand Down
4 changes: 4 additions & 0 deletions builtin/grep.c
Expand Up @@ -209,6 +209,7 @@ static void start_threads(struct grep_opt *opt)
int err; int err;
struct grep_opt *o = grep_opt_dup(opt); struct grep_opt *o = grep_opt_dup(opt);
o->output = strbuf_out; o->output = strbuf_out;
o->debug = 0;
compile_grep_patterns(o); compile_grep_patterns(o);
err = pthread_create(&threads[i], NULL, run, o); err = pthread_create(&threads[i], NULL, run, o);


Expand Down Expand Up @@ -772,6 +773,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
"indicate hit with exit status without output"), "indicate hit with exit status without output"),
OPT_BOOLEAN(0, "all-match", &opt.all_match, OPT_BOOLEAN(0, "all-match", &opt.all_match,
"show only matches from files that match all patterns"), "show only matches from files that match all patterns"),
{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
"show parse tree for grep expression",
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
OPT_GROUP(""), OPT_GROUP(""),
{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager, { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
"pager", "show matching files in the pager", "pager", "show matching files in the pager",
Expand Down
119 changes: 115 additions & 4 deletions grep.c
Expand Up @@ -3,6 +3,10 @@
#include "userdiff.h" #include "userdiff.h"
#include "xdiff-interface.h" #include "xdiff-interface.h"


static int grep_source_load(struct grep_source *gs);
static int grep_source_is_binary(struct grep_source *gs);


static struct grep_pat *create_grep_pat(const char *pat, size_t patlen, static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
const char *origin, int no, const char *origin, int no,
enum grep_pat_token t, enum grep_pat_token t,
Expand Down Expand Up @@ -332,6 +336,87 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
return compile_pattern_or(list); return compile_pattern_or(list);
} }


static void indent(int in)
{
while (in-- > 0)
fputc(' ', stderr);
}

static void dump_grep_pat(struct grep_pat *p)
{
switch (p->token) {
case GREP_AND: fprintf(stderr, "*and*"); break;
case GREP_OPEN_PAREN: fprintf(stderr, "*(*"); break;
case GREP_CLOSE_PAREN: fprintf(stderr, "*)*"); break;
case GREP_NOT: fprintf(stderr, "*not*"); break;
case GREP_OR: fprintf(stderr, "*or*"); break;

case GREP_PATTERN: fprintf(stderr, "pattern"); break;
case GREP_PATTERN_HEAD: fprintf(stderr, "pattern_head"); break;
case GREP_PATTERN_BODY: fprintf(stderr, "pattern_body"); break;
}

switch (p->token) {
default: break;
case GREP_PATTERN_HEAD:
fprintf(stderr, "<head %d>", p->field); break;
case GREP_PATTERN_BODY:
fprintf(stderr, "<body>"); break;
}
switch (p->token) {
default: break;
case GREP_PATTERN_HEAD:
case GREP_PATTERN_BODY:
case GREP_PATTERN:
fprintf(stderr, "%.*s", (int)p->patternlen, p->pattern);
break;
}
fputc('\n', stderr);
}

static void dump_grep_expression_1(struct grep_expr *x, int in)
{
indent(in);
switch (x->node) {
case GREP_NODE_TRUE:
fprintf(stderr, "true\n");
break;
case GREP_NODE_ATOM:
dump_grep_pat(x->u.atom);
break;
case GREP_NODE_NOT:
fprintf(stderr, "(not\n");
dump_grep_expression_1(x->u.unary, in+1);
indent(in);
fprintf(stderr, ")\n");
break;
case GREP_NODE_AND:
fprintf(stderr, "(and\n");
dump_grep_expression_1(x->u.binary.left, in+1);
dump_grep_expression_1(x->u.binary.right, in+1);
indent(in);
fprintf(stderr, ")\n");
break;
case GREP_NODE_OR:
fprintf(stderr, "(or\n");
dump_grep_expression_1(x->u.binary.left, in+1);
dump_grep_expression_1(x->u.binary.right, in+1);
indent(in);
fprintf(stderr, ")\n");
break;
}
}

static void dump_grep_expression(struct grep_opt *opt)
{
struct grep_expr *x = opt->pattern_expression;

if (opt->all_match)
fprintf(stderr, "[all-match]\n");
dump_grep_expression_1(x, 0);
fflush(NULL);
}

static struct grep_expr *grep_true_expr(void) static struct grep_expr *grep_true_expr(void)
{ {
struct grep_expr *z = xcalloc(1, sizeof(*z)); struct grep_expr *z = xcalloc(1, sizeof(*z));
Expand Down Expand Up @@ -395,7 +480,23 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
return header_expr; return header_expr;
} }


void compile_grep_patterns(struct grep_opt *opt) static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y)
{
struct grep_expr *z = x;

while (x) {
assert(x->node == GREP_NODE_OR);
if (x->u.binary.right &&
x->u.binary.right->node == GREP_NODE_TRUE) {
x->u.binary.right = y;
break;
}
x = x->u.binary.right;
}
return z;
}

static void compile_grep_patterns_real(struct grep_opt *opt)
{ {
struct grep_pat *p; struct grep_pat *p;
struct grep_expr *header_expr = prep_header_patterns(opt); struct grep_expr *header_expr = prep_header_patterns(opt);
Expand All @@ -415,7 +516,7 @@ void compile_grep_patterns(struct grep_opt *opt)


if (opt->all_match || header_expr) if (opt->all_match || header_expr)
opt->extended = 1; opt->extended = 1;
else if (!opt->extended) else if (!opt->extended && !opt->debug)
return; return;


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


if (!opt->pattern_expression) if (!opt->pattern_expression)
opt->pattern_expression = header_expr; opt->pattern_expression = header_expr;
else if (opt->all_match)
opt->pattern_expression = grep_splice_or(header_expr,
opt->pattern_expression);
else else
opt->pattern_expression = grep_or_expr(opt->pattern_expression, opt->pattern_expression = grep_or_expr(opt->pattern_expression,
header_expr); header_expr);
opt->all_match = 1; opt->all_match = 1;
} }


void compile_grep_patterns(struct grep_opt *opt)
{
compile_grep_patterns_real(opt);
if (opt->debug)
dump_grep_expression(opt);
}

static void free_pattern_expr(struct grep_expr *x) static void free_pattern_expr(struct grep_expr *x)
{ {
switch (x->node) { switch (x->node) {
Expand Down Expand Up @@ -1358,7 +1469,7 @@ static int grep_source_load_file(struct grep_source *gs)
return 0; return 0;
} }


int grep_source_load(struct grep_source *gs) static int grep_source_load(struct grep_source *gs)
{ {
if (gs->buf) if (gs->buf)
return 0; return 0;
Expand Down Expand Up @@ -1386,7 +1497,7 @@ void grep_source_load_driver(struct grep_source *gs)
grep_attr_unlock(); grep_attr_unlock();
} }


int grep_source_is_binary(struct grep_source *gs) static int grep_source_is_binary(struct grep_source *gs)
{ {
grep_source_load_driver(gs); grep_source_load_driver(gs);
if (gs->driver->binary != -1) if (gs->driver->binary != -1)
Expand Down
4 changes: 2 additions & 2 deletions grep.h
Expand Up @@ -90,6 +90,7 @@ struct grep_opt {
int word_regexp; int word_regexp;
int fixed; int fixed;
int all_match; int all_match;
int debug;
#define GREP_BINARY_DEFAULT 0 #define GREP_BINARY_DEFAULT 0
#define GREP_BINARY_NOMATCH 1 #define GREP_BINARY_NOMATCH 1
#define GREP_BINARY_TEXT 2 #define GREP_BINARY_TEXT 2
Expand Down Expand Up @@ -148,11 +149,10 @@ struct grep_source {


void grep_source_init(struct grep_source *gs, enum grep_source_type type, void grep_source_init(struct grep_source *gs, enum grep_source_type type,
const char *name, const void *identifier); const char *name, const void *identifier);
int grep_source_load(struct grep_source *gs);
void grep_source_clear_data(struct grep_source *gs); void grep_source_clear_data(struct grep_source *gs);
void grep_source_clear(struct grep_source *gs); void grep_source_clear(struct grep_source *gs);
void grep_source_load_driver(struct grep_source *gs); void grep_source_load_driver(struct grep_source *gs);
int grep_source_is_binary(struct grep_source *gs);


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


Expand Down
2 changes: 2 additions & 0 deletions revision.c
Expand Up @@ -1598,6 +1598,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if ((argcount = parse_long_opt("grep", argv, &optarg))) { } else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
add_message_grep(revs, optarg); add_message_grep(revs, optarg);
return argcount; return argcount;
} else if (!strcmp(arg, "--grep-debug")) {
revs->grep_filter.debug = 1;
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) { } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
revs->grep_filter.regflags |= REG_EXTENDED; revs->grep_filter.regflags |= REG_EXTENDED;
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
Expand Down

0 comments on commit 31d69db

Please sign in to comment.