revision: add --grep-reflog to filter commits by reflog messages
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sat, 29 Sep 2012 04:41:28 +0000 (11:41 +0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 29 Sep 2012 18:41:14 +0000 (11:41 -0700)
Similar to --author/--committer which filters commits by author and
committer header fields. --grep-reflog adds a fake "reflog" header to
commit and a grep filter to search on that line.

All rules to --author/--committer apply except no timestamp stripping.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/rev-list-options.txt
grep.c
grep.h
revision.c
t/t7810-grep.sh

index 1fc2a18404bd34a2e1ac9f5fe21d64c1827f13a6..aa7cd9dcfb3bb85c920de5a491bf73c954616846 100644 (file)
@@ -51,6 +51,14 @@ endif::git-rev-list[]
        commits whose author matches any of the given patterns are
        chosen (similarly for multiple `--committer=<pattern>`).
 
+--grep-reflog=<pattern>::
+
+       Limit the commits output to ones with reflog entries that
+       match the specified pattern (regular expression). With
+       more than one `--grep-reflog`, commits whose reflog message
+       matches any of the given patterns are chosen. Ignored unless
+       `--walk-reflogs` is given.
+
 --grep=<pattern>::
 
        Limit the commits output to ones with log message that
diff --git a/grep.c b/grep.c
index 8d73995e87c5f76d6fd0bac0d2a758774415fc6b..d70dcdf0ef2d012f81c0ff0490961bd46d54312d 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -697,6 +697,7 @@ static struct {
 } header_field[] = {
        { "author ", 7 },
        { "committer ", 10 },
+       { "reflog ", 7 },
 };
 
 static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
diff --git a/grep.h b/grep.h
index d54adbe56c4665dad6626f2c8c845da7233bd4a9..6e78b96a2e8a548543bbbd707b079ef849953622 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -30,6 +30,7 @@ enum grep_context {
 enum grep_header_field {
        GREP_HEADER_AUTHOR = 0,
        GREP_HEADER_COMMITTER,
+       GREP_HEADER_REFLOG,
 
        /* Must be at the end of the enum */
        GREP_HEADER_FIELD_MAX
index ae12e11fb74dcc51bfddd2acf94601b2bfba7811..109bec144398699093312eaf79088834ab198f90 100644 (file)
@@ -1595,6 +1595,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
                add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
                return argcount;
+       } else if ((argcount = parse_long_opt("grep-reflog", argv, &optarg))) {
+               add_header_grep(revs, GREP_HEADER_REFLOG, optarg);
+               return argcount;
        } else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
                add_message_grep(revs, optarg);
                return argcount;
@@ -2210,10 +2213,23 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
 
 static int commit_match(struct commit *commit, struct rev_info *opt)
 {
+       int retval;
+       struct strbuf buf = STRBUF_INIT;
        if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
                return 1;
-       return grep_buffer(&opt->grep_filter,
-                          commit->buffer, strlen(commit->buffer));
+       if (opt->reflog_info) {
+               strbuf_addstr(&buf, "reflog ");
+               get_reflog_message(&buf, opt->reflog_info);
+               strbuf_addch(&buf, '\n');
+               strbuf_addstr(&buf, commit->buffer);
+       }
+       if (buf.len)
+               retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
+       else
+               retval = grep_buffer(&opt->grep_filter,
+                                    commit->buffer, strlen(commit->buffer));
+       strbuf_release(&buf);
+       return retval;
 }
 
 static inline int want_ancestry(struct rev_info *revs)
index 30eaa9a54b8b7ea855a2cb781202cfc79e29f217..3a5d0fd77016d58ea11fe205dd0a28857a236632 100755 (executable)
@@ -546,6 +546,32 @@ test_expect_success 'log grep (6)' '
        test_cmp expect actual
 '
 
+test_expect_success 'log grep (7)' '
+       git log -g --grep-reflog="commit: third" --pretty=tformat:%s >actual &&
+       echo third >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log grep (8)' '
+       git log -g --grep-reflog="commit: third" --grep-reflog="commit: second" --pretty=tformat:%s >actual &&
+       {
+               echo third && echo second
+       } >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+       git log -g --grep-reflog="commit: third" --author="Thor" --pretty=tformat:%s >actual &&
+       echo third >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log grep (9)' '
+       git log -g --grep-reflog="commit: third" --author="non-existant" --pretty=tformat:%s >actual &&
+       : >expect &&
+       test_cmp expect actual
+'
+
 test_expect_success 'log with multiple --grep uses union' '
        git log --grep=i --grep=r --format=%s >actual &&
        {