From 8ecae9b032cd0427079d557a3bb6c39116420d4b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Sep 2006 15:43:40 -0700 Subject: revision traversal: prepare for commit log match. This is from a suggestion by Linus, just to mark the locations where we need to modify to actually implement the filtering. We do not have any actual filtering code yet. Signed-off-by: Junio C Hamano --- revision.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'revision.c') diff --git a/revision.c b/revision.c index 6a2539b62..a14457a12 100644 --- a/revision.c +++ b/revision.c @@ -6,6 +6,8 @@ #include "diff.h" #include "refs.h" #include "revision.h" +#include +#include "grep.h" static char *path_name(struct name_path *path, const char *name) { @@ -1045,6 +1047,15 @@ static void mark_boundary_to_show(struct commit *commit) } } +static int commit_match(struct commit *commit, struct rev_info *opt) +{ + if (!opt->header_filter && !opt->message_filter) + return 1; + + /* match it here */ + return 1; +} + struct commit *get_revision(struct rev_info *revs) { struct commit_list *list = revs->commits; @@ -1105,6 +1116,8 @@ struct commit *get_revision(struct rev_info *revs) if (revs->no_merges && commit->parents && commit->parents->next) continue; + if (!commit_match(commit, revs)) + continue; if (revs->prune_fn && revs->dense) { /* Commit without changes? */ if (!(commit->object.flags & TREECHANGE)) { -- cgit v1.2.1 From bd95fcd34543d7d98bff033c00054341165bc9ce Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Sep 2006 17:23:20 -0700 Subject: revision traversal: --author, --committer, and --grep. This adds three options to setup_revisions(), which lets you filter resulting commits by the author name, the committer name and the log message with regexp. Signed-off-by: Junio C Hamano --- revision.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'revision.c') diff --git a/revision.c b/revision.c index a14457a12..26dd41873 100644 --- a/revision.c +++ b/revision.c @@ -674,6 +674,40 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, return 0; } +static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) +{ + char *pat; + int patlen, fldlen; + + if (!revs->header_filter) { + struct grep_opt *opt = xcalloc(1, sizeof(*opt)); + opt->status_only = 1; + opt->pattern_tail = &(opt->pattern_list); + opt->regflags = REG_NEWLINE; + revs->header_filter = opt; + } + + fldlen = strlen(field); + patlen = strlen(pattern); + pat = xmalloc(patlen + fldlen + 3); + sprintf(pat, "^%s %s", field, pattern); + append_grep_pattern(revs->header_filter, pat, + "command line", 0, GREP_PATTERN); +} + +static void add_message_grep(struct rev_info *revs, const char *pattern) +{ + if (!revs->message_filter) { + struct grep_opt *opt = xcalloc(1, sizeof(*opt)); + opt->status_only = 1; + opt->pattern_tail = &(opt->pattern_list); + opt->regflags = REG_NEWLINE; + revs->message_filter = opt; + } + append_grep_pattern(revs->message_filter, pattern, + "command line", 0, GREP_PATTERN); +} + static void add_ignore_packed(struct rev_info *revs, const char *name) { int num = ++revs->num_ignore_packed; @@ -915,6 +949,18 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->relative_date = 1; continue; } + if (!strncmp(arg, "--author=", 9)) { + add_header_grep(revs, "author", arg+9); + continue; + } + if (!strncmp(arg, "--committer=", 12)) { + add_header_grep(revs, "committer", arg+12); + continue; + } + if (!strncmp(arg, "--grep=", 7)) { + add_message_grep(revs, arg+7); + continue; + } opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); if (opts > 0) { revs->diff = 1; @@ -975,6 +1021,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (diff_setup_done(&revs->diffopt) < 0) die("diff_setup_done failed"); + if (revs->header_filter) + compile_grep_patterns(revs->header_filter); + if (revs->message_filter) + compile_grep_patterns(revs->message_filter); + return left; } @@ -1049,10 +1100,33 @@ static void mark_boundary_to_show(struct commit *commit) static int commit_match(struct commit *commit, struct rev_info *opt) { + char *header, *message; + unsigned long header_len, message_len; + if (!opt->header_filter && !opt->message_filter) return 1; - /* match it here */ + header = commit->buffer; + message = strstr(header, "\n\n"); + if (message) { + message += 2; + header_len = message - header - 1; + message_len = strlen(message); + } + else { + header_len = strlen(header); + message = header; + message_len = 0; + } + + if (opt->header_filter && + !grep_buffer(opt->header_filter, NULL, header, header_len)) + return 0; + + if (opt->message_filter && + !grep_buffer(opt->message_filter, NULL, message, message_len)) + return 0; + return 1; } -- cgit v1.2.1 From a2ed6ae402582a3ee76e9b4639848eba261a12de Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 18 Sep 2006 10:07:51 -0700 Subject: git-log --author and --committer are not left-anchored by default I know that I'd prefer a rule where "--author=^Junio" would result in the grep-pattern being "^author Junio", but without the initial '^' it would be "^author .*Junio". Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- revision.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'revision.c') diff --git a/revision.c b/revision.c index 26dd41873..bca122961 100644 --- a/revision.c +++ b/revision.c @@ -677,6 +677,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) { char *pat; + const char *prefix; int patlen, fldlen; if (!revs->header_filter) { @@ -689,8 +690,13 @@ static void add_header_grep(struct rev_info *revs, const char *field, const char fldlen = strlen(field); patlen = strlen(pattern); - pat = xmalloc(patlen + fldlen + 3); - sprintf(pat, "^%s %s", field, pattern); + pat = xmalloc(patlen + fldlen + 10); + prefix = ".*"; + if (*pattern == '^') { + prefix = ""; + pattern++; + } + sprintf(pat, "^%s %s%s", field, prefix, pattern); append_grep_pattern(revs->header_filter, pat, "command line", 0, GREP_PATTERN); } -- cgit v1.2.1 From 2d10c555374df257e32848ba6f77fd73d608645f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 Sep 2006 13:21:56 -0700 Subject: git log: Unify header_filter and message_filter into one. Now we can tell the built-in grep to grep only in head or in body, use that to update --author, --committer, and --grep. Unfortunately, to make --and, --not and other grep boolean expressions useful, as in: # Things written by Junio committed and by Linus and log # does not talk about diff. git log --author=Junio --and --committer=Linus \ --grep-not --grep=diff we will need to do another round of built-in grep core enhancement, because grep boolean expressions are designed to work on one line at a time. Signed-off-by: Junio C Hamano --- revision.c | 74 +++++++++++++++++++++----------------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) (limited to 'revision.c') diff --git a/revision.c b/revision.c index bca122961..93f25130a 100644 --- a/revision.c +++ b/revision.c @@ -674,19 +674,24 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, return 0; } -static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) +static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what) { - char *pat; - const char *prefix; - int patlen, fldlen; - - if (!revs->header_filter) { + if (!revs->grep_filter) { struct grep_opt *opt = xcalloc(1, sizeof(*opt)); opt->status_only = 1; opt->pattern_tail = &(opt->pattern_list); opt->regflags = REG_NEWLINE; - revs->header_filter = opt; + revs->grep_filter = opt; } + append_grep_pattern(revs->grep_filter, ptn, + "command line", 0, what); +} + +static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern) +{ + char *pat; + const char *prefix; + int patlen, fldlen; fldlen = strlen(field); patlen = strlen(pattern); @@ -697,21 +702,12 @@ static void add_header_grep(struct rev_info *revs, const char *field, const char pattern++; } sprintf(pat, "^%s %s%s", field, prefix, pattern); - append_grep_pattern(revs->header_filter, pat, - "command line", 0, GREP_PATTERN); + add_grep(revs, pat, GREP_PATTERN_HEAD); } static void add_message_grep(struct rev_info *revs, const char *pattern) { - if (!revs->message_filter) { - struct grep_opt *opt = xcalloc(1, sizeof(*opt)); - opt->status_only = 1; - opt->pattern_tail = &(opt->pattern_list); - opt->regflags = REG_NEWLINE; - revs->message_filter = opt; - } - append_grep_pattern(revs->message_filter, pattern, - "command line", 0, GREP_PATTERN); + add_grep(revs, pattern, GREP_PATTERN_BODY); } static void add_ignore_packed(struct rev_info *revs, const char *name) @@ -955,6 +951,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->relative_date = 1; continue; } + + /* + * Grepping the commit log + */ if (!strncmp(arg, "--author=", 9)) { add_header_grep(revs, "author", arg+9); continue; @@ -967,6 +967,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch add_message_grep(revs, arg+7); continue; } + opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); if (opts > 0) { revs->diff = 1; @@ -1027,10 +1028,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (diff_setup_done(&revs->diffopt) < 0) die("diff_setup_done failed"); - if (revs->header_filter) - compile_grep_patterns(revs->header_filter); - if (revs->message_filter) - compile_grep_patterns(revs->message_filter); + if (revs->grep_filter) + compile_grep_patterns(revs->grep_filter); return left; } @@ -1106,34 +1105,11 @@ static void mark_boundary_to_show(struct commit *commit) static int commit_match(struct commit *commit, struct rev_info *opt) { - char *header, *message; - unsigned long header_len, message_len; - - if (!opt->header_filter && !opt->message_filter) + if (!opt->grep_filter) return 1; - - header = commit->buffer; - message = strstr(header, "\n\n"); - if (message) { - message += 2; - header_len = message - header - 1; - message_len = strlen(message); - } - else { - header_len = strlen(header); - message = header; - message_len = 0; - } - - if (opt->header_filter && - !grep_buffer(opt->header_filter, NULL, header, header_len)) - return 0; - - if (opt->message_filter && - !grep_buffer(opt->message_filter, NULL, message, message_len)) - return 0; - - return 1; + return grep_buffer(opt->grep_filter, + NULL, /* we say nothing, not even filename */ + commit->buffer, strlen(commit->buffer)); } struct commit *get_revision(struct rev_info *revs) -- cgit v1.2.1