Skip to content

Commit accccde

Browse files
committed
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 <[email protected]>
1 parent 0f871cf commit accccde

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
8080
#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
8181
#define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28)
8282
#define DIFF_OPT_FUNCCONTEXT (1 << 29)
83+
#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
8384

8485
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
8586
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)

diffcore-pickaxe.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,12 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
138138
{
139139
int err;
140140
regex_t regex;
141+
int cflags = REG_EXTENDED | REG_NEWLINE;
141142

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);
143147
if (err) {
144148
char errbuf[1024];
145149
regerror(err, &regex, errbuf, 1024);
@@ -237,7 +241,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
237241
}
238242
regexp = &regex;
239243
} else {
240-
kws = kwsalloc(NULL);
244+
kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
245+
? tolower_trans_tbl : NULL);
241246
kwsincr(kws, needle, len);
242247
kwsprep(kws);
243248
}

revision.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
15591559
revs->grep_filter.regflags |= REG_EXTENDED;
15601560
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
15611561
revs->grep_filter.regflags |= REG_ICASE;
1562+
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
15621563
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
15631564
revs->grep_filter.fixed = 1;
15641565
} else if (!strcmp(arg, "--all-match")) {

t/t4209-log-pickaxe.sh

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 <[email protected]>" -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

0 commit comments

Comments
 (0)