{"thread":{"id":"31182","subject":"[PATCH/RFC] grep: add a grep.patternType configuration setting","startedAt":"2012-08-03T14:53:50Z","lastAt":"2012-08-03T18:22:49Z","messageCount":3,"participants":["J Smith","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"196416","messageId":"1344005630-6541-1-git-send-email-dark.panda@gmail.com","threadId":"31182","inReplyTo":null,"subject":"[PATCH/RFC] grep: add a grep.patternType configuration setting","fromName":"J Smith","fromEmail":"dark.panda@gmail.com","sentAt":"2012-08-03T14:53:50Z","receivedAt":"2012-08-03T14:53:50Z","isPatch":true,"sender":{"key":"dark.panda@gmail.com","avatar":"https://avatars.githubusercontent.com/u/84783?v=4"},"body":"The grep.extendedRegexp configuration setting enables the -E flag on grep\nby default but there are no equivalents for the -G, -F and -P flags.\n\nRather than adding an additional setting for grep.fooRegexp for current\nand future pattern matching options, add a grep.patternType setting that\ncan accept appropriate values for modifying the default grep pattern\nmatching behavior. The current values are \"basic\", \"extended\", \"fixed\",\n\"perl\" and \"default\" for setting -G, -E, -F, -P and the default behavior\nrespectively.\n\nWhen grep.patternType is set to a value other than \"default\", the\ngrep.extendedRegexp setting is ignored. The value of \"default\" restores\nthe current default behavior, including the grep.extendedRegexp\nbehavior.\n\nSigned-off-by: J Smith <dark.panda@gmail.com>\n---\n Documentation/config.txt   |  10 ++-\n Documentation/git-grep.txt |  10 ++-\n builtin/grep.c             | 112 ++++++++++++++++++----------\n grep.h                     |  10 +++\n t/t7810-grep.sh            | 181 +++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 282 insertions(+), 41 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex a95e5a4..6416cae 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1210,8 +1210,16 @@ gitweb.snapshot::\n grep.lineNumber::\n \tIf set to true, enable '-n' option by default.\n\n+grep.patternType::\n+\tSet the default matching behavior. Using a value of 'basic', 'extended',\n+\t'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',\n+\t'--fixed-strings', or '--perl-regexp' option accordingly, while the\n+\tvalue 'default' will return to the default matching behavior.\n+\n grep.extendedRegexp::\n-\tIf set to true, enable '--extended-regexp' option by default.\n+\tIf set to true, enable '--extended-regexp' option by default. This\n+\toption is ignored when the 'grep.patternType' option is set to a value\n+\tother than 'default'.\n\n gpg.program::\n \tUse this custom program instead of \"gpg\" found on $PATH when\ndiff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt\nindex 3bec036..cfecf84 100644\n--- a/Documentation/git-grep.txt\n+++ b/Documentation/git-grep.txt\n@@ -42,8 +42,16 @@ CONFIGURATION\n grep.lineNumber::\n \tIf set to true, enable '-n' option by default.\n\n+grep.patternType::\n+\tSet the default matching behavior. Using a value of 'basic', 'extended',\n+\t'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',\n+\t'--fixed-strings', or '--perl-regexp' option accordingly, while the\n+\tvalue 'default' will return to the default matching behavior.\n+\n grep.extendedRegexp::\n-\tIf set to true, enable '--extended-regexp' option by default.\n+\tIf set to true, enable '--extended-regexp' option by default. This\n+\toption is ignored when the 'grep.patternType' option is set to a value\n+\tother than 'default'.\n\n\n OPTIONS\ndiff --git a/builtin/grep.c b/builtin/grep.c\nindex 29adb0a..7ff64da 100644\n--- a/builtin/grep.c\n+++ b/builtin/grep.c\n@@ -260,6 +260,53 @@ static int wait_all(void)\n }\n #endif\n\n+static int parse_pattern_type_arg(const char *opt, const char *arg)\n+{\n+\tif (!strcmp(arg, \"default\"))\n+\t\treturn GREP_PATTERN_TYPE_UNSPECIFIED;\n+\telse if (!strcmp(arg, \"basic\"))\n+\t\treturn GREP_PATTERN_TYPE_BRE;\n+\telse if (!strcmp(arg, \"extended\"))\n+\t\treturn GREP_PATTERN_TYPE_ERE;\n+\telse if (!strcmp(arg, \"fixed\"))\n+\t\treturn GREP_PATTERN_TYPE_FIXED;\n+\telse if (!strcmp(arg, \"perl\"))\n+\t\treturn GREP_PATTERN_TYPE_PCRE;\n+\tdie(\"bad %s argument: %s\", opt, arg);\n+}\n+\n+static void grep_pattern_type_options(const int pattern_type, struct grep_opt *opt)\n+{\n+\tswitch (pattern_type) {\n+\tcase GREP_PATTERN_TYPE_UNSPECIFIED:\n+\t\t/* fall through */\n+\n+\tcase GREP_PATTERN_TYPE_BRE:\n+\t\topt->fixed = 0;\n+\t\topt->pcre = 0;\n+\t\topt->regflags &= ~REG_EXTENDED;\n+\t\tbreak;\n+\n+\tcase GREP_PATTERN_TYPE_ERE:\n+\t\topt->fixed = 0;\n+\t\topt->pcre = 0;\n+\t\topt->regflags |= REG_EXTENDED;\n+\t\tbreak;\n+\n+\tcase GREP_PATTERN_TYPE_FIXED:\n+\t\topt->fixed = 1;\n+\t\topt->pcre = 0;\n+\t\topt->regflags &= ~REG_EXTENDED;\n+\t\tbreak;\n+\n+\tcase GREP_PATTERN_TYPE_PCRE:\n+\t\topt->fixed = 0;\n+\t\topt->pcre = 1;\n+\t\topt->regflags &= ~REG_EXTENDED;\n+\t\tbreak;\n+\t}\n+}\n+\n static int grep_config(const char *var, const char *value, void *cb)\n {\n \tstruct grep_opt *opt = cb;\n@@ -270,12 +317,17 @@ static int grep_config(const char *var, const char *value, void *cb)\n\n \tif (!strcmp(var, \"grep.extendedregexp\")) {\n \t\tif (git_config_bool(var, value))\n-\t\t\topt->regflags |= REG_EXTENDED;\n+\t\t\topt->extended_regexp_option = 1;\n \t\telse\n-\t\t\topt->regflags &= ~REG_EXTENDED;\n+\t\t\topt->extended_regexp_option = 0;\n \t\treturn 0;\n \t}\n\n+\tif (!strcmp(var, \"grep.patterntype\")) {\n+\t\topt->pattern_type_option = parse_pattern_type_arg(var, value);\n+\t\treturn 0;\n+  }\n+\n \tif (!strcmp(var, \"grep.linenumber\")) {\n \t\topt->linenum = git_config_bool(var, value);\n \t\treturn 0;\n@@ -669,14 +721,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \tint i;\n \tint dummy;\n \tint use_index = 1;\n-\tenum {\n-\t\tpattern_type_unspecified = 0,\n-\t\tpattern_type_bre,\n-\t\tpattern_type_ere,\n-\t\tpattern_type_fixed,\n-\t\tpattern_type_pcre,\n-\t};\n-\tint pattern_type = pattern_type_unspecified;\n+\tint pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;\n\n \tstruct option options[] = {\n \t\tOPT_BOOLEAN(0, \"cached\", &cached,\n@@ -703,18 +748,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t\"descend at most <depth> levels\", PARSE_OPT_NONEG,\n \t\t\tNULL, 1 },\n \t\tOPT_GROUP(\"\"),\n-\t\tOPT_SET_INT('E', \"extended-regexp\", &pattern_type,\n+\t\tOPT_SET_INT('E', \"extended-regexp\", &pattern_type_arg,\n \t\t\t    \"use extended POSIX regular expressions\",\n-\t\t\t    pattern_type_ere),\n-\t\tOPT_SET_INT('G', \"basic-regexp\", &pattern_type,\n+\t\t\t    GREP_PATTERN_TYPE_ERE),\n+\t\tOPT_SET_INT('G', \"basic-regexp\", &pattern_type_arg,\n \t\t\t    \"use basic POSIX regular expressions (default)\",\n-\t\t\t    pattern_type_bre),\n-\t\tOPT_SET_INT('F', \"fixed-strings\", &pattern_type,\n+\t\t\t    GREP_PATTERN_TYPE_BRE),\n+\t\tOPT_SET_INT('F', \"fixed-strings\", &pattern_type_arg,\n \t\t\t    \"interpret patterns as fixed strings\",\n-\t\t\t    pattern_type_fixed),\n-\t\tOPT_SET_INT('P', \"perl-regexp\", &pattern_type,\n+\t\t\t    GREP_PATTERN_TYPE_FIXED),\n+\t\tOPT_SET_INT('P', \"perl-regexp\", &pattern_type_arg,\n \t\t\t    \"use Perl-compatible regular expressions\",\n-\t\t\t    pattern_type_pcre),\n+\t\t\t    GREP_PATTERN_TYPE_PCRE),\n \t\tOPT_GROUP(\"\"),\n \t\tOPT_BOOLEAN('n', \"line-number\", &opt.linenum, \"show line numbers\"),\n \t\tOPT_NEGBIT('h', NULL, &opt.pathname, \"don't show filenames\", 1),\n@@ -799,6 +844,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \topt.header_tail = &opt.header_list;\n \topt.regflags = REG_NEWLINE;\n \topt.max_depth = -1;\n+\topt.pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;\n+\topt.extended_regexp_option = 0;\n\n \tstrcpy(opt.color_context, \"\");\n \tstrcpy(opt.color_filename, \"\");\n@@ -824,27 +871,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n \t\t\t     PARSE_OPT_KEEP_DASHDASH |\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION |\n \t\t\t     PARSE_OPT_NO_INTERNAL_HELP);\n-\tswitch (pattern_type) {\n-\tcase pattern_type_fixed:\n-\t\topt.fixed = 1;\n-\t\topt.pcre = 0;\n-\t\tbreak;\n-\tcase pattern_type_bre:\n-\t\topt.fixed = 0;\n-\t\topt.pcre = 0;\n-\t\topt.regflags &= ~REG_EXTENDED;\n-\t\tbreak;\n-\tcase pattern_type_ere:\n-\t\topt.fixed = 0;\n-\t\topt.pcre = 0;\n-\t\topt.regflags |= REG_EXTENDED;\n-\t\tbreak;\n-\tcase pattern_type_pcre:\n-\t\topt.fixed = 0;\n-\t\topt.pcre = 1;\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak; /* nothing */\n+\n+\tif (pattern_type_arg > GREP_PATTERN_TYPE_UNSPECIFIED)\n+\t\tgrep_pattern_type_options(pattern_type_arg, &opt);\n+\telse {\n+\t\tif (opt.pattern_type_option > GREP_PATTERN_TYPE_UNSPECIFIED)\n+\t\t\tgrep_pattern_type_options(opt.pattern_type_option, &opt);\n+\t\telse if (opt.extended_regexp_option)\n+\t\t\tgrep_pattern_type_options(GREP_PATTERN_TYPE_ERE, &opt);\n \t}\n\n \tif (use_index && !startup_info->have_repository)\ndiff --git a/grep.h b/grep.h\nindex ed7de6b..75afb7b 100644\n--- a/grep.h\n+++ b/grep.h\n@@ -58,6 +58,14 @@ enum grep_expr_node {\n \tGREP_NODE_OR\n };\n\n+enum grep_pattern_type {\n+\tGREP_PATTERN_TYPE_UNSPECIFIED = 0,\n+\tGREP_PATTERN_TYPE_BRE,\n+\tGREP_PATTERN_TYPE_ERE,\n+\tGREP_PATTERN_TYPE_FIXED,\n+\tGREP_PATTERN_TYPE_PCRE\n+};\n+\n struct grep_expr {\n \tenum grep_expr_node node;\n \tunsigned hit;\n@@ -103,6 +111,8 @@ struct grep_opt {\n \tint max_depth;\n \tint funcname;\n \tint funcbody;\n+\tint extended_regexp_option;\n+\tint pattern_type_option;\n \tchar color_context[COLOR_MAXLEN];\n \tchar color_filename[COLOR_MAXLEN];\n \tchar color_function[COLOR_MAXLEN];\ndiff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\nindex 523d041..35d357d 100755\n--- a/t/t7810-grep.sh\n+++ b/t/t7810-grep.sh\n@@ -250,6 +250,84 @@ do\n \t\tgit -c grep.extendedRegexp=true grep \"a+b*c\" ab >actual &&\n \t\ttest_cmp expected actual\n \t'\n+\n+\ttest_expect_success \"grep $L with grep.patterntype=basic\" '\n+\t\techo \"ab:a+bc\" >expected &&\n+\t\tgit -c grep.patterntype=basic grep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"grep $L with grep.patterntype=extended\" '\n+\t\techo \"ab:abc\" >expected &&\n+\t\tgit -c grep.patterntype=extended grep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"grep $L with grep.patterntype=fixed\" '\n+\t\techo \"ab:a+b*c\" >expected &&\n+\t\tgit -c grep.patterntype=fixed grep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success LIBPCRE \"grep $L with grep.patterntype=perl\" '\n+\t\techo \"ab:a+b*c\" >expected &&\n+\t\tgit -c grep.patterntype=perl grep \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"grep $L with grep.patternType=default and grep.extendedRegexp=true\" '\n+\t\techo \"ab:abc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.patternType=default \\\n+\t\t\t-c grep.extendedRegexp=true \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success \"grep $L with grep.extendedRegexp=true and grep.patternType=default\" '\n+\t\techo \"ab:abc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.extendedRegexp=true \\\n+\t\t\t-c grep.patternType=default \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success 'grep $L with grep.patternType=extended and grep.extendedRegexp=false' '\n+\t\techo \"ab:abc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.patternType=extended \\\n+\t\t\t-c grep.extendedRegexp=false \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success 'grep $L with grep.patternType=basic and grep.extendedRegexp=true' '\n+\t\techo \"ab:a+bc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.patternType=basic \\\n+\t\t\t-c grep.extendedRegexp=true \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success 'grep $L with grep.extendedRegexp=false and grep.patternType=extended' '\n+\t\techo \"ab:abc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.extendedRegexp=false \\\n+\t\t\t-c grep.patternType=extended \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n+\n+\ttest_expect_success 'grep $L with grep.extendedRegexp=true and grep.patternType=basic' '\n+\t\techo \"ab:a+bc\" >expected &&\n+\t\tgit \\\n+\t\t\t-c grep.extendedRegexp=true \\\n+\t\t\t-c grep.patternType=basic \\\n+\t\t\tgrep \"a+b*c\" ab >actual &&\n+\t\ttest_cmp expected actual\n+\t'\n done\n\n cat >expected <<EOF\n@@ -761,44 +839,147 @@ test_expect_success 'grep -G invalidpattern properly dies ' '\n \ttest_must_fail git grep -G \"a[\"\n '\n\n+test_expect_success 'grep invalidpattern properly dies with grep.patternType=basic' '\n+\ttest_must_fail git -c grep.patterntype=basic grep \"a[\"\n+'\n+\n test_expect_success 'grep -E invalidpattern properly dies ' '\n \ttest_must_fail git grep -E \"a[\"\n '\n\n+test_expect_success 'grep invalidpattern properly dies with grep.patternType=extended' '\n+\ttest_must_fail git -c grep.patterntype=extended grep \"a[\"\n+'\n+\n test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' '\n \ttest_must_fail git grep -P \"a[\"\n '\n\n+test_expect_success LIBPCRE 'grep invalidpattern properly dies with grep.patternType=perl' '\n+\ttest_must_fail git -c grep.patterntype=perl grep \"a[\"\n+'\n+\n test_expect_success 'grep -G -E -F pattern' '\n \techo \"ab:a+b*c\" >expected &&\n \tgit grep -G -E -F \"a+b*c\" ab >actual &&\n \ttest_cmp expected actual\n '\n\n+test_expect_success 'grep pattern with grep.patternType=basic, =extended, =fixed' '\n+\techo \"ab:a+b*c\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=basic \\\n+\t\t-c grep.patterntype=extended \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\tgrep \"a+b*c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'grep -E -F -G pattern' '\n \techo \"ab:a+bc\" >expected &&\n \tgit grep -E -F -G \"a+b*c\" ab >actual &&\n \ttest_cmp expected actual\n '\n\n+test_expect_success 'grep pattern with grep.patternType=extended, =fixed, =basic' '\n+\techo \"ab:a+bc\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=extended \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\t-c grep.patterntype=basic \\\n+\t\tgrep \"a+b*c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'grep -F -G -E pattern' '\n \techo \"ab:abc\" >expected &&\n \tgit grep -F -G -E \"a+b*c\" ab >actual &&\n \ttest_cmp expected actual\n '\n\n+test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =extended' '\n+\techo \"ab:abc\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\t-c grep.patterntype=basic \\\n+\t\t-c grep.patterntype=extended \\\n+\t\tgrep \"a+b*c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'grep -G -F -P -E pattern' '\n \t>empty &&\n \ttest_must_fail git grep -G -F -P -E \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n \ttest_cmp empty actual\n '\n\n+test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =extended' '\n+\t>empty &&\n+\ttest_must_fail git \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\t-c grep.patterntype=basic \\\n+\t\t-c grep.patterntype=perl \\\n+\t\t-c grep.patterntype=extended \\\n+\t\tgrep \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n+\ttest_cmp empty actual\n+'\n+\n test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '\n \techo \"ab:a+b*c\" >expected &&\n \tgit grep -G -F -E -P \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n \ttest_cmp expected actual\n '\n\n+test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '\n+\techo \"ab:a+b*c\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\t-c grep.patterntype=basic \\\n+\t\t-c grep.patterntype=extended \\\n+\t\t-c grep.patterntype=perl \\\n+\t\tgrep \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success LIBPCRE 'grep -P pattern with grep.patternType=fixed' '\n+\techo \"ab:a+b*c\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\tgrep -P \"a\\x{2b}b\\x{2a}c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'grep -F pattern with grep.patternType=basic' '\n+\techo \"ab:a+b*c\" >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=basic \\\n+\t\tgrep -F \"*c\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'grep -G pattern with grep.patternType=fixed' '\n+\t{\n+\t\techo \"ab:a+b*c\"\n+\t\techo \"ab:a+bc\"\n+\t} >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\tgrep -G \"a+b\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'grep -E pattern with grep.patternType=fixed' '\n+\t{\n+\t\techo \"ab:a+b*c\"\n+\t\techo \"ab:a+bc\"\n+\t\techo \"ab:abc\"\n+\t} >expected &&\n+\tgit \\\n+\t\t-c grep.patterntype=fixed \\\n+\t\tgrep -E \"a+\" ab >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_config() {\n \tgit config \"$1\" \"$2\" &&\n \ttest_when_finished \"git config --unset $1\"\n--\n1.7.11.3\n"},{"id":"196421","messageId":"7vsjc4aq0b.fsf@alter.siamese.dyndns.org","threadId":"31182","inReplyTo":"1344005630-6541-1-git-send-email-dark.panda@gmail.com","subject":"Re: [PATCH/RFC] grep: add a grep.patternType configuration setting","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-08-03T16:39:48Z","receivedAt":"2012-08-03T16:39:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"J Smith <dark.panda@gmail.com> writes:\n\n> The grep.extendedRegexp configuration setting enables the -E flag on grep\n> by default but there are no equivalents for the -G, -F and -P flags.\n>\n> Rather than adding an additional setting for grep.fooRegexp for current\n> and future pattern matching options, add a grep.patternType setting that\n> can accept appropriate values for modifying the default grep pattern\n> matching behavior. The current values are \"basic\", \"extended\", \"fixed\",\n> \"perl\" and \"default\" for setting -G, -E, -F, -P and the default behavior\n> respectively.\n>\n> When grep.patternType is set to a value other than \"default\", the\n> grep.extendedRegexp setting is ignored. The value of \"default\" restores\n> the current default behavior, including the grep.extendedRegexp\n> behavior.\n>\n> Signed-off-by: J Smith <dark.panda@gmail.com>\n> ---\n\nNicely done.\n\n> diff --git a/builtin/grep.c b/builtin/grep.c\n> index 29adb0a..7ff64da 100644\n> --- a/builtin/grep.c\n> +++ b/builtin/grep.c\n> @@ -260,6 +260,53 @@ static int wait_all(void)\n>  }\n>  #endif\n>\n> +static int parse_pattern_type_arg(const char *opt, const char *arg)\n> +{\n> +\tif (!strcmp(arg, \"default\"))\n> +\t\treturn GREP_PATTERN_TYPE_UNSPECIFIED;\n> +\telse if (!strcmp(arg, \"basic\"))\n> +\t\treturn GREP_PATTERN_TYPE_BRE;\n> +\telse if (!strcmp(arg, \"extended\"))\n> +\t\treturn GREP_PATTERN_TYPE_ERE;\n> +\telse if (!strcmp(arg, \"fixed\"))\n> +\t\treturn GREP_PATTERN_TYPE_FIXED;\n> +\telse if (!strcmp(arg, \"perl\"))\n> +\t\treturn GREP_PATTERN_TYPE_PCRE;\n> +\tdie(\"bad %s argument: %s\", opt, arg);\n> +}\n> +\n> +static void grep_pattern_type_options(const int pattern_type, struct grep_opt *opt)\n> +{\n> +\tswitch (pattern_type) {\n> +\tcase GREP_PATTERN_TYPE_UNSPECIFIED:\n> +\t\t/* fall through */\n> +\n> +\tcase GREP_PATTERN_TYPE_BRE:\n> +\t\topt->fixed = 0;\n> +\t\topt->pcre = 0;\n> +\t\topt->regflags &= ~REG_EXTENDED;\n> +\t\tbreak;\n> +\n> +\tcase GREP_PATTERN_TYPE_ERE:\n> +\t\topt->fixed = 0;\n> +\t\topt->pcre = 0;\n> +\t\topt->regflags |= REG_EXTENDED;\n> +\t\tbreak;\n> +\n> +\tcase GREP_PATTERN_TYPE_FIXED:\n> +\t\topt->fixed = 1;\n> +\t\topt->pcre = 0;\n> +\t\topt->regflags &= ~REG_EXTENDED;\n> +\t\tbreak;\n> +\n> +\tcase GREP_PATTERN_TYPE_PCRE:\n> +\t\topt->fixed = 0;\n> +\t\topt->pcre = 1;\n> +\t\topt->regflags &= ~REG_EXTENDED;\n> +\t\tbreak;\n> +\t}\n> +}\n> +\n>  static int grep_config(const char *var, const char *value, void *cb)\n>  {\n>  \tstruct grep_opt *opt = cb;\n> @@ -270,12 +317,17 @@ static int grep_config(const char *var, const char *value, void *cb)\n>\n>  \tif (!strcmp(var, \"grep.extendedregexp\")) {\n>  \t\tif (git_config_bool(var, value))\n> -\t\t\topt->regflags |= REG_EXTENDED;\n> +\t\t\topt->extended_regexp_option = 1;\n>  \t\telse\n> -\t\t\topt->regflags &= ~REG_EXTENDED;\n> +\t\t\topt->extended_regexp_option = 0;\n>  \t\treturn 0;\n>  \t}\n>\n> +\tif (!strcmp(var, \"grep.patterntype\")) {\n> +\t\topt->pattern_type_option = parse_pattern_type_arg(var, value);\n> +\t\treturn 0;\n> +  }\n> +\n>  \tif (!strcmp(var, \"grep.linenumber\")) {\n>  \t\topt->linenum = git_config_bool(var, value);\n>  \t\treturn 0;\n> ...\n> @@ -799,6 +844,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)\n> +\topt.pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;\n> +\topt.extended_regexp_option = 0;\n> ...\n> +\n> +\tif (pattern_type_arg > GREP_PATTERN_TYPE_UNSPECIFIED)\n> +\t\tgrep_pattern_type_options(pattern_type_arg, &opt);\n> +\telse {\n> +\t\tif (opt.pattern_type_option > GREP_PATTERN_TYPE_UNSPECIFIED)\n> +\t\t\tgrep_pattern_type_options(opt.pattern_type_option, &opt);\n> +\t\telse if (opt.extended_regexp_option)\n> +\t\t\tgrep_pattern_type_options(GREP_PATTERN_TYPE_ERE, &opt);\n\nOk, so while reading the configuration and command line options, we\ndo not touch the real fields that affect how the comparison is done,\n(namely: regflags, fixed, ...), and just \"buffer\" what we read so\nfar in extended_regexp_option and pattern_type_option, and at the\nvery end set the real fields to their appropriate values.\n\nMuch nicer than the drafts in earlier discussion.  One micronit is\nthat probably it is preferrable to do '!=' instead of '>', as we are\nonly trying to see if it is unspecified on the command line (hence\nneed to pay attention to configuration) and do not care how the\nenums are ordered, but that is nothing that requires a re-roll.\n\n> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh\n> index 523d041..35d357d 100755\n> --- a/t/t7810-grep.sh\n> +++ b/t/t7810-grep.sh\n> ...\n> +test_expect_success 'grep -G pattern with grep.patternType=fixed' '\n> +\t{\n> +\t\techo \"ab:a+b*c\"\n> +\t\techo \"ab:a+bc\"\n> +\t} >expected &&\n> +\tgit \\\n> +\t\t-c grep.patterntype=fixed \\\n> +\t\tgrep -G \"a+b\" ab >actual &&\n> +\ttest_cmp expected actual\n> +'\n\nAll the new tests in the script looked very well thought out.\n\nI noticed that this particular one will still succeed when somebody\nbreaks your code to ignore the configuration (as -G \"a+b\" would give\nthe expected match) or give higher precedence to the configuration\n(as fixed \"a+b\" also will give the expected match).  Not that it is\nwrong to have such a test that is unlikely to catch certain kinds of\nregressions in the suite, and the particular kind of breakage will\nbe caught by the next test (snipped) anyway.\n\nWill queue.  Thanks.\n"},{"id":"196426","messageId":"CADFUPge8LdBKHFrs32gFtzFwvvbK6OSxfMBdHF6fyRwtcCocTw@mail.gmail.com","threadId":"31182","inReplyTo":"7vsjc4aq0b.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH/RFC] grep: add a grep.patternType configuration setting","fromName":"J Smith","fromEmail":"dark.panda@gmail.com","sentAt":"2012-08-03T18:22:49Z","receivedAt":"2012-08-03T18:22:49Z","isPatch":true,"sender":{"key":"dark.panda@gmail.com","avatar":"https://avatars.githubusercontent.com/u/84783?v=4"},"body":"On Fri, Aug 3, 2012 at 12:39 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Much nicer than the drafts in earlier discussion.  One micronit is\n> that probably it is preferrable to do '!=' instead of '>', as we are\n> only trying to see if it is unspecified on the command line (hence\n> need to pay attention to configuration) and do not care how the\n> enums are ordered, but that is nothing that requires a re-roll.\n\nTrue enough. Old habits I guess, eh?\n\n> All the new tests in the script looked very well thought out.\n>\n> I noticed that this particular one will still succeed when somebody\n> breaks your code to ignore the configuration (as -G \"a+b\" would give\n> the expected match) or give higher precedence to the configuration\n> (as fixed \"a+b\" also will give the expected match).  Not that it is\n> wrong to have such a test that is unlikely to catch certain kinds of\n> regressions in the suite, and the particular kind of breakage will\n> be caught by the next test (snipped) anyway.\n\nYeah, that test is kind of iffy, but does no harm I suppose.\n\n> Will queue.  Thanks.\n\nGreat, thanks. Been an informative experience for a first-time git\npatcher. Cheers.\n"}]}