pickaxe: allow -i to search in patch case-insensitively

"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>

Junio C Hamano committed Feb 21, 2012 at 01:02 UTC accccde483c3cfd55ef55037e8802ca0baaee5a1
4 files changed +128 -2
diff.h
+1
@@ -80,6 +80,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
80 #define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
81 #define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28)
82 #define DIFF_OPT_FUNCCONTEXT (1 << 29)
83 +#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
84
85 #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
86 #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
diffcore-pickaxe.c
+7 -2
@@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
138 {
139 int err;
140 regex_t regex;
141 + int cflags = REG_EXTENDED | REG_NEWLINE;
142
142 - err = regcomp(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
143 + if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
144 + cflags |= REG_ICASE;
145 +
146 + err = regcomp(&regex, o->pickaxe, cflags);
147 if (err) {
148 char errbuf[1024];
149 regerror(err, &regex, errbuf, 1024);
@@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
241 }
242 regexp = &regex;
243 } else {
240 - kws = kwsalloc(NULL);
244 + kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
245 + ? tolower_trans_tbl : NULL);
246 kwsincr(kws, needle, len);
247 kwsprep(kws);
248 }
revision.c
+1
@@ -1559,6 +1559,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1559 revs->grep_filter.regflags |= REG_EXTENDED;
1560 } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
1561 revs->grep_filter.regflags |= REG_ICASE;
1562 + DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
1563 } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
1564 revs->grep_filter.fixed = 1;
1565 } else if (!strcmp(arg, "--all-match")) {
t/t4209-log-pickaxe.sh new
+119
@@ -0,0 +1,119 @@
1 +#!/bin/sh
2 +
3 +test_description='log --grep/--author/--regexp-ignore-case/-S/-G'
4 +. ./test-lib.sh
5 +
6 +test_expect_success setup '
7 + >file &&
8 + git add file &&
9 + test_tick &&
10 + git commit -m initial &&
11 +
12 + echo Picked >file &&
13 + test_tick &&
14 + git commit -a --author="Another Person <another@example.com>" -m second
15 +'
16 +
17 +test_expect_success 'log --grep' '
18 + git log --grep=initial --format=%H >actual &&
19 + git rev-parse --verify HEAD^ >expect &&
20 + test_cmp expect actual
21 +'
22 +
23 +test_expect_success 'log --grep --regexp-ignore-case' '
24 + git log --regexp-ignore-case --grep=InItial --format=%H >actual &&
25 + git rev-parse --verify HEAD^ >expect &&
26 + test_cmp expect actual
27 +'
28 +
29 +test_expect_success 'log --grep -i' '
30 + git log -i --grep=InItial --format=%H >actual &&
31 + git rev-parse --verify HEAD^ >expect &&
32 + test_cmp expect actual
33 +'
34 +
35 +test_expect_success 'log --author --regexp-ignore-case' '
36 + git log --regexp-ignore-case --author=person --format=%H >actual &&
37 + git rev-parse --verify HEAD >expect &&
38 + test_cmp expect actual
39 +'
40 +
41 +test_expect_success 'log --author -i' '
42 + git log -i --author=person --format=%H >actual &&
43 + git rev-parse --verify HEAD >expect &&
44 + test_cmp expect actual
45 +'
46 +
47 +test_expect_success 'log -G (nomatch)' '
48 + git log -Gpicked --format=%H >actual &&
49 + >expect &&
50 + test_cmp expect actual
51 +'
52 +
53 +test_expect_success 'log -G (match)' '
54 + git log -GPicked --format=%H >actual &&
55 + git rev-parse --verify HEAD >expect &&
56 + test_cmp expect actual
57 +'
58 +
59 +test_expect_success 'log -G --regexp-ignore-case (nomatch)' '
60 + git log --regexp-ignore-case -Gpickle --format=%H >actual &&
61 + >expect &&
62 + test_cmp expect actual
63 +'
64 +
65 +test_expect_success 'log -G -i (nomatch)' '
66 + git log -i -Gpickle --format=%H >actual &&
67 + >expect &&
68 + test_cmp expect actual
69 +'
70 +
71 +test_expect_success 'log -G --regexp-ignore-case (match)' '
72 + git log --regexp-ignore-case -Gpicked --format=%H >actual &&
73 + git rev-parse --verify HEAD >expect &&
74 + test_cmp expect actual
75 +'
76 +
77 +test_expect_success 'log -G -i (match)' '
78 + git log -i -Gpicked --format=%H >actual &&
79 + git rev-parse --verify HEAD >expect &&
80 + test_cmp expect actual
81 +'
82 +
83 +test_expect_success 'log -S (nomatch)' '
84 + git log -Spicked --format=%H >actual &&
85 + >expect &&
86 + test_cmp expect actual
87 +'
88 +
89 +test_expect_success 'log -S (match)' '
90 + git log -SPicked --format=%H >actual &&
91 + git rev-parse --verify HEAD >expect &&
92 + test_cmp expect actual
93 +'
94 +
95 +test_expect_success 'log -S --regexp-ignore-case (match)' '
96 + git log --regexp-ignore-case -Spicked --format=%H >actual &&
97 + git rev-parse --verify HEAD >expect &&
98 + test_cmp expect actual
99 +'
100 +
101 +test_expect_success 'log -S -i (match)' '
102 + git log -i -Spicked --format=%H >actual &&
103 + git rev-parse --verify HEAD >expect &&
104 + test_cmp expect actual
105 +'
106 +
107 +test_expect_success 'log -S --regexp-ignore-case (nomatch)' '
108 + git log --regexp-ignore-case -Spickle --format=%H >actual &&
109 + >expect &&
110 + test_cmp expect actual
111 +'
112 +
113 +test_expect_success 'log -S -i (nomatch)' '
114 + git log -i -Spickle --format=%H >actual &&
115 + >expect &&
116 + test_cmp expect actual
117 +'
118 +
119 +test_done