summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-grep.txt4
-rw-r--r--grep.c33
-rw-r--r--grep.h2
-rwxr-xr-xt/t7810-grep.sh5
4 files changed, 41 insertions, 3 deletions
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index e150c77cff..c3306f3a3b 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -29,7 +29,9 @@ SYNOPSIS
DESCRIPTION
-----------
Look for specified patterns in the tracked files in the work tree, blobs
-registered in the index file, or blobs in given tree objects.
+registered in the index file, or blobs in given tree objects. Patterns
+are lists of one or more search expressions separated by newline
+characters. An empty string as search expression matches all lines.
CONFIGURATION
diff --git a/grep.c b/grep.c
index c35a7ce57d..02258039d9 100644
--- a/grep.c
+++ b/grep.c
@@ -9,7 +9,7 @@ static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
enum grep_header_field field)
{
struct grep_pat *p = xcalloc(1, sizeof(*p));
- p->pattern = pat;
+ p->pattern = xmemdupz(pat, patlen);
p->patternlen = patlen;
p->origin = origin;
p->no = no;
@@ -23,6 +23,36 @@ static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
**tail = p;
*tail = &p->next;
p->next = NULL;
+
+ switch (p->token) {
+ case GREP_PATTERN: /* atom */
+ case GREP_PATTERN_HEAD:
+ case GREP_PATTERN_BODY:
+ for (;;) {
+ struct grep_pat *new_pat;
+ size_t len = 0;
+ char *cp = p->pattern + p->patternlen, *nl = NULL;
+ while (++len <= p->patternlen) {
+ if (*(--cp) == '\n') {
+ nl = cp;
+ break;
+ }
+ }
+ if (!nl)
+ break;
+ new_pat = create_grep_pat(nl + 1, len - 1, p->origin,
+ p->no, p->token, p->field);
+ new_pat->next = p->next;
+ if (!p->next)
+ *tail = &new_pat->next;
+ p->next = new_pat;
+ *nl = '\0';
+ p->patternlen -= len;
+ }
+ break;
+ default:
+ break;
+ }
}
void append_header_grep_pattern(struct grep_opt *opt,
@@ -408,6 +438,7 @@ void free_grep_patterns(struct grep_opt *opt)
free_pcre_regexp(p);
else
regfree(&p->regexp);
+ free(p->pattern);
break;
default:
break;
diff --git a/grep.h b/grep.h
index cd055cdfa8..5b083affe1 100644
--- a/grep.h
+++ b/grep.h
@@ -35,7 +35,7 @@ struct grep_pat {
const char *origin;
int no;
enum grep_pat_token token;
- const char *pattern;
+ char *pattern;
size_t patternlen;
enum grep_header_field field;
regex_t regexp;
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 6379ad60bc..bc9a522085 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -322,6 +322,11 @@ test_expect_success 'grep -f, multiple patterns' '
test_cmp expected actual
'
+test_expect_success 'grep, multiple patterns' '
+ git grep "$(cat patterns)" >actual &&
+ test_cmp expected actual
+'
+
cat >expected <<EOF
file:foo mmap bar
file:foo_mmap bar