grep: add a grep.patternType configuration setting

The grep.extendedRegexp configuration setting enables the -E flag on grep by default but there are no equivalents for the -G, -F and -P flags. Rather than adding an additional setting for grep.fooRegexp for current and future pattern matching options, add a grep.patternType setting that can accept appropriate values for modifying the default grep pattern matching behavior. The current values are "basic", "extended", "fixed", "perl" and "default" for setting -G, -E, -F, -P and the default behavior respectively. When grep.patternType is set to a value other than "default", the grep.extendedRegexp setting is ignored. The value of "default" restores the current default behavior, including the grep.extendedRegexp behavior. Signed-off-by: J Smith <dark.panda@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

J Smith committed Aug 3, 2012 at 10:53 UTC 84befcd0a4a074e2ae191c32be09d2e82d5db114
5 files changed +281 -42
Documentation/config.txt
+9 -1
@@ -1196,8 +1196,16 @@ gitweb.snapshot::
1196 grep.lineNumber::
1197 If set to true, enable '-n' option by default.
1198
1199 +grep.patternType::
1200 + Set the default matching behavior. Using a value of 'basic', 'extended',
1201 + 'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',
1202 + '--fixed-strings', or '--perl-regexp' option accordingly, while the
1203 + value 'default' will return to the default matching behavior.
1204 +
1205 grep.extendedRegexp::
1200 - If set to true, enable '--extended-regexp' option by default.
1206 + If set to true, enable '--extended-regexp' option by default. This
1207 + option is ignored when the 'grep.patternType' option is set to a value
1208 + other than 'default'.
1209
1210 gpg.program::
1211 Use this custom program instead of "gpg" found on $PATH when
Documentation/git-grep.txt
+9 -1
@@ -42,8 +42,16 @@ CONFIGURATION
42 grep.lineNumber::
43 If set to true, enable '-n' option by default.
44
45 +grep.patternType::
46 + Set the default matching behavior. Using a value of 'basic', 'extended',
47 + 'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',
48 + '--fixed-strings', or '--perl-regexp' option accordingly, while the
49 + value 'default' will return to the default matching behavior.
50 +
51 grep.extendedRegexp::
46 - If set to true, enable '--extended-regexp' option by default.
52 + If set to true, enable '--extended-regexp' option by default. This
53 + option is ignored when the 'grep.patternType' option is set to a value
54 + other than 'default'.
55
56
57 OPTIONS
builtin/grep.c
+72 -40
@@ -260,6 +260,53 @@ static int wait_all(void)
260 }
261 #endif
262
263 +static int parse_pattern_type_arg(const char *opt, const char *arg)
264 +{
265 + if (!strcmp(arg, "default"))
266 + return GREP_PATTERN_TYPE_UNSPECIFIED;
267 + else if (!strcmp(arg, "basic"))
268 + return GREP_PATTERN_TYPE_BRE;
269 + else if (!strcmp(arg, "extended"))
270 + return GREP_PATTERN_TYPE_ERE;
271 + else if (!strcmp(arg, "fixed"))
272 + return GREP_PATTERN_TYPE_FIXED;
273 + else if (!strcmp(arg, "perl"))
274 + return GREP_PATTERN_TYPE_PCRE;
275 + die("bad %s argument: %s", opt, arg);
276 +}
277 +
278 +static void grep_pattern_type_options(const int pattern_type, struct grep_opt *opt)
279 +{
280 + switch (pattern_type) {
281 + case GREP_PATTERN_TYPE_UNSPECIFIED:
282 + /* fall through */
283 +
284 + case GREP_PATTERN_TYPE_BRE:
285 + opt->fixed = 0;
286 + opt->pcre = 0;
287 + opt->regflags &= ~REG_EXTENDED;
288 + break;
289 +
290 + case GREP_PATTERN_TYPE_ERE:
291 + opt->fixed = 0;
292 + opt->pcre = 0;
293 + opt->regflags |= REG_EXTENDED;
294 + break;
295 +
296 + case GREP_PATTERN_TYPE_FIXED:
297 + opt->fixed = 1;
298 + opt->pcre = 0;
299 + opt->regflags &= ~REG_EXTENDED;
300 + break;
301 +
302 + case GREP_PATTERN_TYPE_PCRE:
303 + opt->fixed = 0;
304 + opt->pcre = 1;
305 + opt->regflags &= ~REG_EXTENDED;
306 + break;
307 + }
308 +}
309 +
310 static int grep_config(const char *var, const char *value, void *cb)
311 {
312 struct grep_opt *opt = cb;
@@ -270,12 +317,17 @@ static int grep_config(const char *var, const char *value, void *cb)
317
318 if (!strcmp(var, "grep.extendedregexp")) {
319 if (git_config_bool(var, value))
273 - opt->regflags |= REG_EXTENDED;
320 + opt->extended_regexp_option = 1;
321 else
275 - opt->regflags &= ~REG_EXTENDED;
322 + opt->extended_regexp_option = 0;
323 return 0;
324 }
325
326 + if (!strcmp(var, "grep.patterntype")) {
327 + opt->pattern_type_option = parse_pattern_type_arg(var, value);
328 + return 0;
329 + }
330 +
331 if (!strcmp(var, "grep.linenumber")) {
332 opt->linenum = git_config_bool(var, value);
333 return 0;
@@ -669,14 +721,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
721 int i;
722 int dummy;
723 int use_index = 1;
672 - enum {
673 - pattern_type_unspecified = 0,
674 - pattern_type_bre,
675 - pattern_type_ere,
676 - pattern_type_fixed,
677 - pattern_type_pcre,
678 - };
679 - int pattern_type = pattern_type_unspecified;
724 + int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
725
726 struct option options[] = {
727 OPT_BOOLEAN(0, "cached", &cached,
@@ -703,18 +748,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
748 "descend at most <depth> levels", PARSE_OPT_NONEG,
749 NULL, 1 },
750 OPT_GROUP(""),
706 - OPT_SET_INT('E', "extended-regexp", &pattern_type,
751 + OPT_SET_INT('E', "extended-regexp", &pattern_type_arg,
752 "use extended POSIX regular expressions",
708 - pattern_type_ere),
709 - OPT_SET_INT('G', "basic-regexp", &pattern_type,
753 + GREP_PATTERN_TYPE_ERE),
754 + OPT_SET_INT('G', "basic-regexp", &pattern_type_arg,
755 "use basic POSIX regular expressions (default)",
711 - pattern_type_bre),
712 - OPT_SET_INT('F', "fixed-strings", &pattern_type,
756 + GREP_PATTERN_TYPE_BRE),
757 + OPT_SET_INT('F', "fixed-strings", &pattern_type_arg,
758 "interpret patterns as fixed strings",
714 - pattern_type_fixed),
715 - OPT_SET_INT('P', "perl-regexp", &pattern_type,
759 + GREP_PATTERN_TYPE_FIXED),
760 + OPT_SET_INT('P', "perl-regexp", &pattern_type_arg,
761 "use Perl-compatible regular expressions",
717 - pattern_type_pcre),
762 + GREP_PATTERN_TYPE_PCRE),
763 OPT_GROUP(""),
764 OPT_BOOLEAN('n', "line-number", &opt.linenum, "show line numbers"),
765 OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
@@ -799,6 +844,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
844 opt.header_tail = &opt.header_list;
845 opt.regflags = REG_NEWLINE;
846 opt.max_depth = -1;
847 + opt.pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;
848 + opt.extended_regexp_option = 0;
849
850 strcpy(opt.color_context, "");
851 strcpy(opt.color_filename, "");
@@ -824,28 +871,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
871 PARSE_OPT_KEEP_DASHDASH |
872 PARSE_OPT_STOP_AT_NON_OPTION |
873 PARSE_OPT_NO_INTERNAL_HELP);
827 - switch (pattern_type) {
828 - case pattern_type_fixed:
829 - opt.fixed = 1;
830 - opt.pcre = 0;
831 - break;
832 - case pattern_type_bre:
833 - opt.fixed = 0;
834 - opt.pcre = 0;
835 - opt.regflags &= ~REG_EXTENDED;
836 - break;
837 - case pattern_type_ere:
838 - opt.fixed = 0;
839 - opt.pcre = 0;
840 - opt.regflags |= REG_EXTENDED;
841 - break;
842 - case pattern_type_pcre:
843 - opt.fixed = 0;
844 - opt.pcre = 1;
845 - break;
846 - default:
847 - break; /* nothing */
848 - }
874 +
875 + if (pattern_type_arg != GREP_PATTERN_TYPE_UNSPECIFIED)
876 + grep_pattern_type_options(pattern_type_arg, &opt);
877 + else if (opt.pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED)
878 + grep_pattern_type_options(opt.pattern_type_option, &opt);
879 + else if (opt.extended_regexp_option)
880 + grep_pattern_type_options(GREP_PATTERN_TYPE_ERE, &opt);
881
882 if (use_index && !startup_info->have_repository)
883 /* die the same way as if we did it at the beginning */
grep.h
+10
@@ -58,6 +58,14 @@ enum grep_expr_node {
58 GREP_NODE_OR
59 };
60
61 +enum grep_pattern_type {
62 + GREP_PATTERN_TYPE_UNSPECIFIED = 0,
63 + GREP_PATTERN_TYPE_BRE,
64 + GREP_PATTERN_TYPE_ERE,
65 + GREP_PATTERN_TYPE_FIXED,
66 + GREP_PATTERN_TYPE_PCRE
67 +};
68 +
69 struct grep_expr {
70 enum grep_expr_node node;
71 unsigned hit;
@@ -103,6 +111,8 @@ struct grep_opt {
111 int max_depth;
112 int funcname;
113 int funcbody;
114 + int extended_regexp_option;
115 + int pattern_type_option;
116 char color_context[COLOR_MAXLEN];
117 char color_filename[COLOR_MAXLEN];
118 char color_function[COLOR_MAXLEN];
t/t7810-grep.sh
+181
@@ -250,6 +250,84 @@ do
250 git -c grep.extendedRegexp=true grep "a+b*c" ab >actual &&
251 test_cmp expected actual
252 '
253 +
254 + test_expect_success "grep $L with grep.patterntype=basic" '
255 + echo "ab:a+bc" >expected &&
256 + git -c grep.patterntype=basic grep "a+b*c" ab >actual &&
257 + test_cmp expected actual
258 + '
259 +
260 + test_expect_success "grep $L with grep.patterntype=extended" '
261 + echo "ab:abc" >expected &&
262 + git -c grep.patterntype=extended grep "a+b*c" ab >actual &&
263 + test_cmp expected actual
264 + '
265 +
266 + test_expect_success "grep $L with grep.patterntype=fixed" '
267 + echo "ab:a+b*c" >expected &&
268 + git -c grep.patterntype=fixed grep "a+b*c" ab >actual &&
269 + test_cmp expected actual
270 + '
271 +
272 + test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" '
273 + echo "ab:a+b*c" >expected &&
274 + git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" ab >actual &&
275 + test_cmp expected actual
276 + '
277 +
278 + test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
279 + echo "ab:abc" >expected &&
280 + git \
281 + -c grep.patternType=default \
282 + -c grep.extendedRegexp=true \
283 + grep "a+b*c" ab >actual &&
284 + test_cmp expected actual
285 + '
286 +
287 + test_expect_success "grep $L with grep.extendedRegexp=true and grep.patternType=default" '
288 + echo "ab:abc" >expected &&
289 + git \
290 + -c grep.extendedRegexp=true \
291 + -c grep.patternType=default \
292 + grep "a+b*c" ab >actual &&
293 + test_cmp expected actual
294 + '
295 +
296 + test_expect_success 'grep $L with grep.patternType=extended and grep.extendedRegexp=false' '
297 + echo "ab:abc" >expected &&
298 + git \
299 + -c grep.patternType=extended \
300 + -c grep.extendedRegexp=false \
301 + grep "a+b*c" ab >actual &&
302 + test_cmp expected actual
303 + '
304 +
305 + test_expect_success 'grep $L with grep.patternType=basic and grep.extendedRegexp=true' '
306 + echo "ab:a+bc" >expected &&
307 + git \
308 + -c grep.patternType=basic \
309 + -c grep.extendedRegexp=true \
310 + grep "a+b*c" ab >actual &&
311 + test_cmp expected actual
312 + '
313 +
314 + test_expect_success 'grep $L with grep.extendedRegexp=false and grep.patternType=extended' '
315 + echo "ab:abc" >expected &&
316 + git \
317 + -c grep.extendedRegexp=false \
318 + -c grep.patternType=extended \
319 + grep "a+b*c" ab >actual &&
320 + test_cmp expected actual
321 + '
322 +
323 + test_expect_success 'grep $L with grep.extendedRegexp=true and grep.patternType=basic' '
324 + echo "ab:a+bc" >expected &&
325 + git \
326 + -c grep.extendedRegexp=true \
327 + -c grep.patternType=basic \
328 + grep "a+b*c" ab >actual &&
329 + test_cmp expected actual
330 + '
331 done
332
333 cat >expected <<EOF
@@ -772,44 +850,147 @@ test_expect_success 'grep -G invalidpattern properly dies ' '
850 test_must_fail git grep -G "a["
851 '
852
853 +test_expect_success 'grep invalidpattern properly dies with grep.patternType=basic' '
854 + test_must_fail git -c grep.patterntype=basic grep "a["
855 +'
856 +
857 test_expect_success 'grep -E invalidpattern properly dies ' '
858 test_must_fail git grep -E "a["
859 '
860
861 +test_expect_success 'grep invalidpattern properly dies with grep.patternType=extended' '
862 + test_must_fail git -c grep.patterntype=extended grep "a["
863 +'
864 +
865 test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' '
866 test_must_fail git grep -P "a["
867 '
868
869 +test_expect_success LIBPCRE 'grep invalidpattern properly dies with grep.patternType=perl' '
870 + test_must_fail git -c grep.patterntype=perl grep "a["
871 +'
872 +
873 test_expect_success 'grep -G -E -F pattern' '
874 echo "ab:a+b*c" >expected &&
875 git grep -G -E -F "a+b*c" ab >actual &&
876 test_cmp expected actual
877 '
878
879 +test_expect_success 'grep pattern with grep.patternType=basic, =extended, =fixed' '
880 + echo "ab:a+b*c" >expected &&
881 + git \
882 + -c grep.patterntype=basic \
883 + -c grep.patterntype=extended \
884 + -c grep.patterntype=fixed \
885 + grep "a+b*c" ab >actual &&
886 + test_cmp expected actual
887 +'
888 +
889 test_expect_success 'grep -E -F -G pattern' '
890 echo "ab:a+bc" >expected &&
891 git grep -E -F -G "a+b*c" ab >actual &&
892 test_cmp expected actual
893 '
894
895 +test_expect_success 'grep pattern with grep.patternType=extended, =fixed, =basic' '
896 + echo "ab:a+bc" >expected &&
897 + git \
898 + -c grep.patterntype=extended \
899 + -c grep.patterntype=fixed \
900 + -c grep.patterntype=basic \
901 + grep "a+b*c" ab >actual &&
902 + test_cmp expected actual
903 +'
904 +
905 test_expect_success 'grep -F -G -E pattern' '
906 echo "ab:abc" >expected &&
907 git grep -F -G -E "a+b*c" ab >actual &&
908 test_cmp expected actual
909 '
910
911 +test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =extended' '
912 + echo "ab:abc" >expected &&
913 + git \
914 + -c grep.patterntype=fixed \
915 + -c grep.patterntype=basic \
916 + -c grep.patterntype=extended \
917 + grep "a+b*c" ab >actual &&
918 + test_cmp expected actual
919 +'
920 +
921 test_expect_success 'grep -G -F -P -E pattern' '
922 >empty &&
923 test_must_fail git grep -G -F -P -E "a\x{2b}b\x{2a}c" ab >actual &&
924 test_cmp empty actual
925 '
926
927 +test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =extended' '
928 + >empty &&
929 + test_must_fail git \
930 + -c grep.patterntype=fixed \
931 + -c grep.patterntype=basic \
932 + -c grep.patterntype=perl \
933 + -c grep.patterntype=extended \
934 + grep "a\x{2b}b\x{2a}c" ab >actual &&
935 + test_cmp empty actual
936 +'
937 +
938 test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
939 echo "ab:a+b*c" >expected &&
940 git grep -G -F -E -P "a\x{2b}b\x{2a}c" ab >actual &&
941 test_cmp expected actual
942 '
943
944 +test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '
945 + echo "ab:a+b*c" >expected &&
946 + git \
947 + -c grep.patterntype=fixed \
948 + -c grep.patterntype=basic \
949 + -c grep.patterntype=extended \
950 + -c grep.patterntype=perl \
951 + grep "a\x{2b}b\x{2a}c" ab >actual &&
952 + test_cmp expected actual
953 +'
954 +
955 +test_expect_success LIBPCRE 'grep -P pattern with grep.patternType=fixed' '
956 + echo "ab:a+b*c" >expected &&
957 + git \
958 + -c grep.patterntype=fixed \
959 + grep -P "a\x{2b}b\x{2a}c" ab >actual &&
960 + test_cmp expected actual
961 +'
962 +
963 +test_expect_success 'grep -F pattern with grep.patternType=basic' '
964 + echo "ab:a+b*c" >expected &&
965 + git \
966 + -c grep.patterntype=basic \
967 + grep -F "*c" ab >actual &&
968 + test_cmp expected actual
969 +'
970 +
971 +test_expect_success 'grep -G pattern with grep.patternType=fixed' '
972 + {
973 + echo "ab:a+b*c"
974 + echo "ab:a+bc"
975 + } >expected &&
976 + git \
977 + -c grep.patterntype=fixed \
978 + grep -G "a+b" ab >actual &&
979 + test_cmp expected actual
980 +'
981 +
982 +test_expect_success 'grep -E pattern with grep.patternType=fixed' '
983 + {
984 + echo "ab:a+b*c"
985 + echo "ab:a+bc"
986 + echo "ab:abc"
987 + } >expected &&
988 + git \
989 + -c grep.patterntype=fixed \
990 + grep -E "a+" ab >actual &&
991 + test_cmp expected actual
992 +'
993 +
994 test_config() {
995 git config "$1" "$2" &&
996 test_when_finished "git config --unset $1"