pickaxe: allow -i to search in patch case-insensitively
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Feb 2012 09:02:46 +0000 (01:02 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 29 Feb 2012 00:15:29 +0000 (16:15 -0800)
"git log -S<string>" is a useful way to find the last commit in the
codebase that touched the <string>. As it was designed to be used by a
porcelain script to dig the history starting from a block of text that
appear in the starting commit, it never had to look for anything but an
exact match.

When used by an end user who wants to look for the last commit that
removed a string (e.g. name of a variable) that he vaguely remembers,
however, it is useful to support case insensitive match.

When given the "--regexp-ignore-case" (or "-i") option, which originally
was designed to affect case sensitivity of the search done in the commit
log part, e.g. "log --grep", the matches made with -S/-G pickaxe search is
done case insensitively now.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff.h
diffcore-pickaxe.c
revision.c
t/t4209-log-pickaxe.sh [new file with mode: 0755]

diff --git a/diff.h b/diff.h
index 0c51724493f76461b67d6ef8f5556852819ad809..436b574a23e7808ff38d87d306d8437894478052 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -80,6 +80,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
 #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
 #define DIFF_OPT_DIRSTAT_BY_LINE     (1 << 28)
 #define DIFF_OPT_FUNCCONTEXT         (1 << 29)
+#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
 
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
index 380a837b5b136ae88d374ae8a7326c87597107fc..ed23eb4bdda3b595ac956ba65557b1dc7d50426d 100644 (file)
@@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
 {
        int err;
        regex_t regex;
+       int cflags = REG_EXTENDED | REG_NEWLINE;
 
-       err = regcomp(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
+       if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
+               cflags |= REG_ICASE;
+
+       err = regcomp(&regex, o->pickaxe, cflags);
        if (err) {
                char errbuf[1024];
                regerror(err, &regex, errbuf, 1024);
@@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
                }
                regexp = &regex;
        } else {
-               kws = kwsalloc(NULL);
+               kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
+                              ? tolower_trans_tbl : NULL);
                kwsincr(kws, needle, len);
                kwsprep(kws);
        }
index 8764dde381111cfc9c8ea7eb3856223de9786ec9..971b7dc98da9edcd7d320de38838046e747f9666 100644 (file)
@@ -1559,6 +1559,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->grep_filter.regflags |= REG_EXTENDED;
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
                revs->grep_filter.regflags |= REG_ICASE;
+               DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
                revs->grep_filter.fixed = 1;
        } else if (!strcmp(arg, "--all-match")) {
diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh
new file mode 100755 (executable)
index 0000000..eed7273
--- /dev/null
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
+. ./test-lib.sh
+
+test_expect_success setup '
+       >file &&
+       git add file &&
+       test_tick &&
+       git commit -m initial &&
+
+       echo Picked >file &&
+       test_tick &&
+       git commit -a --author="Another Person <another@example.com>" -m second
+'
+
+test_expect_success 'log --grep' '
+       git log --grep=initial --format=%H >actual &&
+       git rev-parse --verify HEAD^ >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log --grep --regexp-ignore-case' '
+       git log --regexp-ignore-case --grep=InItial --format=%H >actual &&
+       git rev-parse --verify HEAD^ >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log --grep -i' '
+       git log -i --grep=InItial --format=%H >actual &&
+       git rev-parse --verify HEAD^ >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log --author --regexp-ignore-case' '
+       git log --regexp-ignore-case --author=person --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log --author -i' '
+       git log -i --author=person --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G (nomatch)' '
+       git log -Gpicked --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G (match)' '
+       git log -GPicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G --regexp-ignore-case (nomatch)' '
+       git log --regexp-ignore-case -Gpickle --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G -i (nomatch)' '
+       git log -i -Gpickle --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G --regexp-ignore-case (match)' '
+       git log --regexp-ignore-case -Gpicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -G -i (match)' '
+       git log -i -Gpicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S (nomatch)' '
+       git log -Spicked --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S (match)' '
+       git log -SPicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S --regexp-ignore-case (match)' '
+       git log --regexp-ignore-case -Spicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S -i (match)' '
+       git log -i -Spicked --format=%H >actual &&
+       git rev-parse --verify HEAD >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S --regexp-ignore-case (nomatch)' '
+       git log --regexp-ignore-case -Spickle --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'log -S -i (nomatch)' '
+       git log -i -Spickle --format=%H >actual &&
+       >expect &&
+       test_cmp expect actual
+'
+
+test_done