Skip to content

Commit 2147cb2

Browse files
committed
Merge branch 'rs/maint-grep-F' into maint
"git grep -e '$pattern'", unlike the case where the patterns are read from a file, did not treat individual lines in the given pattern argument as separate regular expressions as it should. By René Scharfe * rs/maint-grep-F: grep: stop leaking line strings with -f grep: support newline separated pattern list grep: factor out do_append_grep_pat() grep: factor out create_grep_pat()
2 parents e2d484c + ec83061 commit 2147cb2

File tree

5 files changed

+68
-24
lines changed

5 files changed

+68
-24
lines changed

Documentation/git-grep.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ SYNOPSIS
3131
DESCRIPTION
3232
-----------
3333
Look for specified patterns in the tracked files in the work tree, blobs
34-
registered in the index file, or blobs in given tree objects.
34+
registered in the index file, or blobs in given tree objects. Patterns
35+
are lists of one or more search expressions separated by newline
36+
characters. An empty string as search expression matches all lines.
3537

3638

3739
CONFIGURATION

builtin/grep.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,15 +600,12 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
600600
if (!patterns)
601601
die_errno(_("cannot open '%s'"), arg);
602602
while (strbuf_getline(&sb, patterns, '\n') == 0) {
603-
char *s;
604-
size_t len;
605-
606603
/* ignore empty line like grep does */
607604
if (sb.len == 0)
608605
continue;
609606

610-
s = strbuf_detach(&sb, &len);
611-
append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN);
607+
append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
608+
GREP_PATTERN);
612609
}
613610
if (!from_stdin)
614611
fclose(patterns);

grep.c

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,64 @@
33
#include "userdiff.h"
44
#include "xdiff-interface.h"
55

6-
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
6+
static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
7+
const char *origin, int no,
8+
enum grep_pat_token t,
9+
enum grep_header_field field)
710
{
811
struct grep_pat *p = xcalloc(1, sizeof(*p));
9-
p->pattern = pat;
10-
p->patternlen = strlen(pat);
11-
p->origin = "header";
12-
p->no = 0;
13-
p->token = GREP_PATTERN_HEAD;
12+
p->pattern = xmemdupz(pat, patlen);
13+
p->patternlen = patlen;
14+
p->origin = origin;
15+
p->no = no;
16+
p->token = t;
1417
p->field = field;
15-
*opt->header_tail = p;
16-
opt->header_tail = &p->next;
18+
return p;
19+
}
20+
21+
static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
22+
{
23+
**tail = p;
24+
*tail = &p->next;
1725
p->next = NULL;
26+
27+
switch (p->token) {
28+
case GREP_PATTERN: /* atom */
29+
case GREP_PATTERN_HEAD:
30+
case GREP_PATTERN_BODY:
31+
for (;;) {
32+
struct grep_pat *new_pat;
33+
size_t len = 0;
34+
char *cp = p->pattern + p->patternlen, *nl = NULL;
35+
while (++len <= p->patternlen) {
36+
if (*(--cp) == '\n') {
37+
nl = cp;
38+
break;
39+
}
40+
}
41+
if (!nl)
42+
break;
43+
new_pat = create_grep_pat(nl + 1, len - 1, p->origin,
44+
p->no, p->token, p->field);
45+
new_pat->next = p->next;
46+
if (!p->next)
47+
*tail = &new_pat->next;
48+
p->next = new_pat;
49+
*nl = '\0';
50+
p->patternlen -= len;
51+
}
52+
break;
53+
default:
54+
break;
55+
}
56+
}
57+
58+
void append_header_grep_pattern(struct grep_opt *opt,
59+
enum grep_header_field field, const char *pat)
60+
{
61+
struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
62+
GREP_PATTERN_HEAD, field);
63+
do_append_grep_pat(&opt->header_tail, p);
1864
}
1965

2066
void append_grep_pattern(struct grep_opt *opt, const char *pat,
@@ -26,15 +72,8 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
2672
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
2773
const char *origin, int no, enum grep_pat_token t)
2874
{
29-
struct grep_pat *p = xcalloc(1, sizeof(*p));
30-
p->pattern = pat;
31-
p->patternlen = patlen;
32-
p->origin = origin;
33-
p->no = no;
34-
p->token = t;
35-
*opt->pattern_tail = p;
36-
opt->pattern_tail = &p->next;
37-
p->next = NULL;
75+
struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, 0);
76+
do_append_grep_pat(&opt->pattern_tail, p);
3877
}
3978

4079
struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
@@ -430,6 +469,7 @@ void free_grep_patterns(struct grep_opt *opt)
430469
free_pcre_regexp(p);
431470
else
432471
regfree(&p->regexp);
472+
free(p->pattern);
433473
break;
434474
default:
435475
break;

grep.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct grep_pat {
3838
const char *origin;
3939
int no;
4040
enum grep_pat_token token;
41-
const char *pattern;
41+
char *pattern;
4242
size_t patternlen;
4343
enum grep_header_field field;
4444
regex_t regexp;

t/t7810-grep.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ test_expect_success 'grep -f, multiple patterns' '
351351
test_cmp expected actual
352352
'
353353

354+
test_expect_success 'grep, multiple patterns' '
355+
git grep "$(cat patterns)" >actual &&
356+
test_cmp expected actual
357+
'
358+
354359
cat >expected <<EOF
355360
file:foo mmap bar
356361
file:foo_mmap bar

0 commit comments

Comments
 (0)