Skip to content

Commit a14f6ca

Browse files
committed
Merge branch 'jc/maint-log-grep' into maint
* jc/maint-log-grep: log --author/--committer: really match only with name part
2 parents 26c10c7 + a4d7d2c commit a14f6ca

File tree

4 files changed

+114
-17
lines changed

4 files changed

+114
-17
lines changed

grep.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22
#include "grep.h"
33
#include "xdiff-interface.h"
44

5+
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
6+
{
7+
struct grep_pat *p = xcalloc(1, sizeof(*p));
8+
p->pattern = pat;
9+
p->origin = "header";
10+
p->no = 0;
11+
p->token = GREP_PATTERN_HEAD;
12+
p->field = field;
13+
*opt->pattern_tail = p;
14+
opt->pattern_tail = &p->next;
15+
p->next = NULL;
16+
}
17+
518
void append_grep_pattern(struct grep_opt *opt, const char *pat,
619
const char *origin, int no, enum grep_pat_token t)
720
{
@@ -247,16 +260,53 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
247260
}
248261
}
249262

263+
static int strip_timestamp(char *bol, char **eol_p)
264+
{
265+
char *eol = *eol_p;
266+
int ch;
267+
268+
while (bol < --eol) {
269+
if (*eol != '>')
270+
continue;
271+
*eol_p = ++eol;
272+
ch = *eol;
273+
*eol = '\0';
274+
return ch;
275+
}
276+
return 0;
277+
}
278+
279+
static struct {
280+
const char *field;
281+
size_t len;
282+
} header_field[] = {
283+
{ "author ", 7 },
284+
{ "committer ", 10 },
285+
};
286+
250287
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
251288
{
252289
int hit = 0;
253290
int at_true_bol = 1;
291+
int saved_ch = 0;
254292
regmatch_t pmatch[10];
255293

256294
if ((p->token != GREP_PATTERN) &&
257295
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
258296
return 0;
259297

298+
if (p->token == GREP_PATTERN_HEAD) {
299+
const char *field;
300+
size_t len;
301+
assert(p->field < ARRAY_SIZE(header_field));
302+
field = header_field[p->field].field;
303+
len = header_field[p->field].len;
304+
if (strncmp(bol, field, len))
305+
return 0;
306+
bol += len;
307+
saved_ch = strip_timestamp(bol, &eol);
308+
}
309+
260310
again:
261311
if (!opt->fixed) {
262312
regex_t *exp = &p->regexp;
@@ -298,6 +348,8 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
298348
goto again;
299349
}
300350
}
351+
if (p->token == GREP_PATTERN_HEAD && saved_ch)
352+
*eol = saved_ch;
301353
return hit;
302354
}
303355

grep.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@ enum grep_context {
1717
GREP_CONTEXT_BODY,
1818
};
1919

20+
enum grep_header_field {
21+
GREP_HEADER_AUTHOR = 0,
22+
GREP_HEADER_COMMITTER,
23+
};
24+
2025
struct grep_pat {
2126
struct grep_pat *next;
2227
const char *origin;
2328
int no;
2429
enum grep_pat_token token;
2530
const char *pattern;
31+
enum grep_header_field field;
2632
regex_t regexp;
2733
};
2834

@@ -74,6 +80,7 @@ struct grep_opt {
7480
};
7581

7682
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
83+
extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
7784
extern void compile_grep_patterns(struct grep_opt *opt);
7885
extern void free_grep_patterns(struct grep_opt *opt);
7986
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);

revision.c

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -953,22 +953,9 @@ static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token
953953
append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
954954
}
955955

956-
static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
956+
static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
957957
{
958-
char *pat;
959-
const char *prefix;
960-
int patlen, fldlen;
961-
962-
fldlen = strlen(field);
963-
patlen = strlen(pattern);
964-
pat = xmalloc(patlen + fldlen + 10);
965-
prefix = ".*";
966-
if (*pattern == '^') {
967-
prefix = "";
968-
pattern++;
969-
}
970-
sprintf(pat, "^%s %s%s", field, prefix, pattern);
971-
add_grep(revs, pat, GREP_PATTERN_HEAD);
958+
append_header_grep_pattern(&revs->grep_filter, field, pattern);
972959
}
973960

974961
static void add_message_grep(struct rev_info *revs, const char *pattern)
@@ -1154,9 +1141,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
11541141
* Grepping the commit log
11551142
*/
11561143
else if (!prefixcmp(arg, "--author=")) {
1157-
add_header_grep(revs, "author", arg+9);
1144+
add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
11581145
} else if (!prefixcmp(arg, "--committer=")) {
1159-
add_header_grep(revs, "committer", arg+12);
1146+
add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
11601147
} else if (!prefixcmp(arg, "--grep=")) {
11611148
add_message_grep(revs, arg+7);
11621149
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {

t/t7002-grep.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ test_expect_success setup '
2222
mkdir t &&
2323
echo test >t/t &&
2424
git add file x y z t/t &&
25+
test_tick &&
2526
git commit -m initial
2627
'
2728

@@ -113,4 +114,54 @@ do
113114

114115
done
115116

117+
test_expect_success 'log grep setup' '
118+
echo a >>file &&
119+
test_tick &&
120+
GIT_AUTHOR_NAME="With * Asterisk" \
121+
GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
122+
git commit -a -m "second" &&
123+
124+
echo a >>file &&
125+
test_tick &&
126+
git commit -a -m "third"
127+
128+
'
129+
130+
test_expect_success 'log grep (1)' '
131+
git log --author=author --pretty=tformat:%s >actual &&
132+
( echo third ; echo initial ) >expect &&
133+
test_cmp expect actual
134+
'
135+
136+
test_expect_success 'log grep (2)' '
137+
git log --author=" * " -F --pretty=tformat:%s >actual &&
138+
( echo second ) >expect &&
139+
test_cmp expect actual
140+
'
141+
142+
test_expect_success 'log grep (3)' '
143+
git log --author="^A U" --pretty=tformat:%s >actual &&
144+
( echo third ; echo initial ) >expect &&
145+
test_cmp expect actual
146+
'
147+
148+
test_expect_success 'log grep (4)' '
149+
git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
150+
( echo second ) >expect &&
151+
test_cmp expect actual
152+
'
153+
154+
test_expect_success 'log grep (5)' '
155+
git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
156+
( echo third ; echo initial ) >expect &&
157+
test_cmp expect actual
158+
'
159+
160+
test_expect_success 'log grep (6)' '
161+
git log --author=-0700 --pretty=tformat:%s >actual &&
162+
>expect &&
163+
test_cmp expect actual
164+
165+
'
166+
116167
test_done

0 commit comments

Comments
 (0)