Code

grep: Allow case insensitive search of fixed-strings
authorBrian Collins <bricollins@gmail.com>
Fri, 6 Nov 2009 09:22:35 +0000 (01:22 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 Nov 2009 00:06:46 +0000 (16:06 -0800)
"git grep" currently an error when you combine the -F and -i flags.
This isn't in line with how GNU grep handles it.

This patch allows the simultaneous use of those flags.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Brian Collins <bricollins@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-grep.c
grep.c
grep.h
t/t7002-grep.sh

index 761799d7d0afd62ecba99d703a8595664faa4723..b41ad1e43a1e4bc4bec8d4d6b8c0fd68aa6aa92f 100644 (file)
@@ -367,7 +367,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                push_arg("-h");
        if (opt->regflags & REG_EXTENDED)
                push_arg("-E");
-       if (opt->regflags & REG_ICASE)
+       if (opt->ignore_case)
                push_arg("-i");
        if (opt->binary == GREP_BINARY_NOMATCH)
                push_arg("-I");
@@ -706,8 +706,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_GROUP(""),
                OPT_BOOLEAN('v', "invert-match", &opt.invert,
                        "show non-matching lines"),
-               OPT_BIT('i', "ignore-case", &opt.regflags,
-                       "case insensitive matching", REG_ICASE),
+               OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case,
+                       "case insensitive matching"),
                OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
                        "match patterns only at word boundaries"),
                OPT_SET_INT('a', "text", &opt.binary,
@@ -830,6 +830,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                external_grep_allowed = 0;
        if (!opt.pattern_list)
                die("no pattern given.");
+       if (!opt.fixed && opt.ignore_case)
+               opt.regflags |= REG_ICASE;
        if ((opt.regflags != REG_NEWLINE) && opt.fixed)
                die("cannot mix --fixed-strings and regexp");
        compile_grep_patterns(&opt);
diff --git a/grep.c b/grep.c
index 5d162dae6e43cdfcf6b20627df088a73cbfa98dc..bdadf2c0ccfafc18011beee3bc05754860392523 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -41,6 +41,7 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
        int err;
 
        p->word_regexp = opt->word_regexp;
+       p->ignore_case = opt->ignore_case;
 
        if (opt->fixed || is_fixed(p->pattern))
                p->fixed = 1;
@@ -262,9 +263,15 @@ static void show_name(struct grep_opt *opt, const char *name)
        printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
 }
 
-static int fixmatch(const char *pattern, char *line, regmatch_t *match)
+
+static int fixmatch(const char *pattern, char *line, int ignore_case, regmatch_t *match)
 {
-       char *hit = strstr(line, pattern);
+       char *hit;
+       if (ignore_case)
+               hit = strcasestr(line, pattern);
+       else
+               hit = strstr(line, pattern);
+
        if (!hit) {
                match->rm_so = match->rm_eo = -1;
                return REG_NOMATCH;
@@ -326,7 +333,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 
  again:
        if (p->fixed)
-               hit = !fixmatch(p->pattern, bol, pmatch);
+               hit = !fixmatch(p->pattern, bol, p->ignore_case, pmatch);
        else
                hit = !regexec(&p->regexp, bol, 1, pmatch, eflags);
 
diff --git a/grep.h b/grep.h
index f6eecc62c038f212fa4efc8648f13f61bf937452..75370f60d7091becd3eaddf3b7069c26fca8c125 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -32,6 +32,7 @@ struct grep_pat {
        enum grep_header_field field;
        regex_t regexp;
        unsigned fixed:1;
+       unsigned ignore_case:1;
        unsigned word_regexp:1;
 };
 
@@ -64,6 +65,7 @@ struct grep_opt {
        regex_t regexp;
        int linenum;
        int invert;
+       int ignore_case;
        int status_only;
        int name_only;
        int unmatch_name_only;
index ae56a36eacbc2d9a796742c974fa498705f71104..35a1e7a5d430a8b8565f3b767e31810df4463485 100755 (executable)
@@ -14,6 +14,7 @@ int main(int argc, const char **argv)
 {
        printf("Hello world.\n");
        return 0;
+       /* char ?? */
 }
 EOF
 
@@ -345,4 +346,13 @@ test_expect_success 'grep from a subdirectory to search wider area (2)' '
        )
 '
 
+cat >expected <<EOF
+hello.c:int main(int argc, const char **argv)
+EOF
+
+test_expect_success 'grep -Fi' '
+       git grep -Fi "CHAR *" >actual &&
+       test_cmp expected actual
+'
+
 test_done