aboutsummaryrefslogtreecommitdiff
path: root/revision.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-09-17 17:23:20 -0700
committerJunio C Hamano <junkio@cox.net>2006-09-20 11:14:39 -0700
commitbd95fcd34543d7d98bff033c00054341165bc9ce (patch)
tree0fa7058f054dff5055e16233373c451749b4e61a /revision.c
parent8ecae9b032cd0427079d557a3bb6c39116420d4b (diff)
downloadgit-bd95fcd34543d7d98bff033c00054341165bc9ce.tar.gz
git-bd95fcd34543d7d98bff033c00054341165bc9ce.tar.xz
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 <junkio@cox.net>
Diffstat (limited to 'revision.c')
-rw-r--r--revision.c76
1 files changed, 75 insertions, 1 deletions
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;
}