mirror of
https://github.com/git/git
synced 2024-10-30 04:01:21 +00:00
Merge branch 'jc/maint-log-grep' into maint
* jc/maint-log-grep: log --author/--committer: really match only with name part
This commit is contained in:
commit
a14f6ca26a
4 changed files with 114 additions and 17 deletions
52
grep.c
52
grep.c
|
@ -2,6 +2,19 @@
|
|||
#include "grep.h"
|
||||
#include "xdiff-interface.h"
|
||||
|
||||
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
|
||||
{
|
||||
struct grep_pat *p = xcalloc(1, sizeof(*p));
|
||||
p->pattern = pat;
|
||||
p->origin = "header";
|
||||
p->no = 0;
|
||||
p->token = GREP_PATTERN_HEAD;
|
||||
p->field = field;
|
||||
*opt->pattern_tail = p;
|
||||
opt->pattern_tail = &p->next;
|
||||
p->next = NULL;
|
||||
}
|
||||
|
||||
void append_grep_pattern(struct grep_opt *opt, const char *pat,
|
||||
const char *origin, int no, enum grep_pat_token t)
|
||||
{
|
||||
|
@ -247,16 +260,53 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
|
|||
}
|
||||
}
|
||||
|
||||
static int strip_timestamp(char *bol, char **eol_p)
|
||||
{
|
||||
char *eol = *eol_p;
|
||||
int ch;
|
||||
|
||||
while (bol < --eol) {
|
||||
if (*eol != '>')
|
||||
continue;
|
||||
*eol_p = ++eol;
|
||||
ch = *eol;
|
||||
*eol = '\0';
|
||||
return ch;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *field;
|
||||
size_t len;
|
||||
} header_field[] = {
|
||||
{ "author ", 7 },
|
||||
{ "committer ", 10 },
|
||||
};
|
||||
|
||||
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
|
||||
{
|
||||
int hit = 0;
|
||||
int at_true_bol = 1;
|
||||
int saved_ch = 0;
|
||||
regmatch_t pmatch[10];
|
||||
|
||||
if ((p->token != GREP_PATTERN) &&
|
||||
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
|
||||
return 0;
|
||||
|
||||
if (p->token == GREP_PATTERN_HEAD) {
|
||||
const char *field;
|
||||
size_t len;
|
||||
assert(p->field < ARRAY_SIZE(header_field));
|
||||
field = header_field[p->field].field;
|
||||
len = header_field[p->field].len;
|
||||
if (strncmp(bol, field, len))
|
||||
return 0;
|
||||
bol += len;
|
||||
saved_ch = strip_timestamp(bol, &eol);
|
||||
}
|
||||
|
||||
again:
|
||||
if (!opt->fixed) {
|
||||
regex_t *exp = &p->regexp;
|
||||
|
@ -298,6 +348,8 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
|
|||
goto again;
|
||||
}
|
||||
}
|
||||
if (p->token == GREP_PATTERN_HEAD && saved_ch)
|
||||
*eol = saved_ch;
|
||||
return hit;
|
||||
}
|
||||
|
||||
|
|
7
grep.h
7
grep.h
|
@ -17,12 +17,18 @@ enum grep_context {
|
|||
GREP_CONTEXT_BODY,
|
||||
};
|
||||
|
||||
enum grep_header_field {
|
||||
GREP_HEADER_AUTHOR = 0,
|
||||
GREP_HEADER_COMMITTER,
|
||||
};
|
||||
|
||||
struct grep_pat {
|
||||
struct grep_pat *next;
|
||||
const char *origin;
|
||||
int no;
|
||||
enum grep_pat_token token;
|
||||
const char *pattern;
|
||||
enum grep_header_field field;
|
||||
regex_t regexp;
|
||||
};
|
||||
|
||||
|
@ -74,6 +80,7 @@ struct grep_opt {
|
|||
};
|
||||
|
||||
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
|
||||
extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
|
||||
extern void compile_grep_patterns(struct grep_opt *opt);
|
||||
extern void free_grep_patterns(struct grep_opt *opt);
|
||||
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
|
||||
|
|
21
revision.c
21
revision.c
|
@ -953,22 +953,9 @@ static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token
|
|||
append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
|
||||
}
|
||||
|
||||
static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
|
||||
static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
|
||||
{
|
||||
char *pat;
|
||||
const char *prefix;
|
||||
int patlen, fldlen;
|
||||
|
||||
fldlen = strlen(field);
|
||||
patlen = strlen(pattern);
|
||||
pat = xmalloc(patlen + fldlen + 10);
|
||||
prefix = ".*";
|
||||
if (*pattern == '^') {
|
||||
prefix = "";
|
||||
pattern++;
|
||||
}
|
||||
sprintf(pat, "^%s %s%s", field, prefix, pattern);
|
||||
add_grep(revs, pat, GREP_PATTERN_HEAD);
|
||||
append_header_grep_pattern(&revs->grep_filter, field, pattern);
|
||||
}
|
||||
|
||||
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
|
|||
* Grepping the commit log
|
||||
*/
|
||||
else if (!prefixcmp(arg, "--author=")) {
|
||||
add_header_grep(revs, "author", arg+9);
|
||||
add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
|
||||
} else if (!prefixcmp(arg, "--committer=")) {
|
||||
add_header_grep(revs, "committer", arg+12);
|
||||
add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
|
||||
} else if (!prefixcmp(arg, "--grep=")) {
|
||||
add_message_grep(revs, arg+7);
|
||||
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
|
||||
|
|
|
@ -22,6 +22,7 @@ test_expect_success setup '
|
|||
mkdir t &&
|
||||
echo test >t/t &&
|
||||
git add file x y z t/t &&
|
||||
test_tick &&
|
||||
git commit -m initial
|
||||
'
|
||||
|
||||
|
@ -113,4 +114,54 @@ do
|
|||
|
||||
done
|
||||
|
||||
test_expect_success 'log grep setup' '
|
||||
echo a >>file &&
|
||||
test_tick &&
|
||||
GIT_AUTHOR_NAME="With * Asterisk" \
|
||||
GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
|
||||
git commit -a -m "second" &&
|
||||
|
||||
echo a >>file &&
|
||||
test_tick &&
|
||||
git commit -a -m "third"
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (1)' '
|
||||
git log --author=author --pretty=tformat:%s >actual &&
|
||||
( echo third ; echo initial ) >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (2)' '
|
||||
git log --author=" * " -F --pretty=tformat:%s >actual &&
|
||||
( echo second ) >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (3)' '
|
||||
git log --author="^A U" --pretty=tformat:%s >actual &&
|
||||
( echo third ; echo initial ) >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (4)' '
|
||||
git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
|
||||
( echo second ) >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (5)' '
|
||||
git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
|
||||
( echo third ; echo initial ) >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'log grep (6)' '
|
||||
git log --author=-0700 --pretty=tformat:%s >actual &&
|
||||
>expect &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Loading…
Reference in a new issue