grep: remove regflags from the public grep_opt API
Refactor calls to the grep machinery to always pass opt.ignore_case & opt.extended_regexp_option instead of setting the equivalent regflags bits. The bug fixed when making -i work with -P in commitmaint9e3cbc59d5("log: make --regexp-ignore-case work with --perl-regexp", 2017-05-20) was really just plastering over the code smell which this change fixes. The reason for adding the extensive commentary here is that I discovered some subtle complexity in implementing this that really should be called out explicitly to future readers. Before this change we'd rely on the difference between `extended_regexp_option` and `regflags` to serve as a membrane between our preliminary parsing of grep.extendedRegexp and grep.patternType, and what we decided to do internally. Now that those two are the same thing, it's necessary to unset `extended_regexp_option` just before we commit in cases where both of those config variables are set. See84befcd0a4("grep: add a grep.patternType configuration setting", 2012-08-03) for the code and documentation related to that. The explanation of why the if/else branches in grep_commit_pattern_type() are ordered the way they are exists in that commit message, but I think it's worth calling this subtlety out explicitly with a comment for future readers. Even though grep_commit_pattern_type() is the only caller of grep_set_pattern_type_option() it's simpler to reset the extended_regexp_option flag in the latter, since 2/3 branches in the former would otherwise need to reset it, this way we can do it in one place. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
							parent
							
								
									b07ed4e532
								
							
						
					
					
						commit
						07a3d41173
					
				|  | @ -1169,8 +1169,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) | ||||||
|  |  | ||||||
| 	if (!opt.pattern_list) | 	if (!opt.pattern_list) | ||||||
| 		die(_("no pattern given.")); | 		die(_("no pattern given.")); | ||||||
| 	if (!opt.fixed && opt.ignore_case) |  | ||||||
| 		opt.regflags |= REG_ICASE; |  | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * We have to find "--" in a separate pass, because its presence | 	 * We have to find "--" in a separate pass, because its presence | ||||||
|  |  | ||||||
							
								
								
									
										43
									
								
								grep.c
								
								
								
								
							
							
						
						
									
										43
									
								
								grep.c
								
								
								
								
							|  | @ -35,7 +35,6 @@ void init_grep_defaults(void) | ||||||
| 	memset(opt, 0, sizeof(*opt)); | 	memset(opt, 0, sizeof(*opt)); | ||||||
| 	opt->relative = 1; | 	opt->relative = 1; | ||||||
| 	opt->pathname = 1; | 	opt->pathname = 1; | ||||||
| 	opt->regflags = REG_NEWLINE; |  | ||||||
| 	opt->max_depth = -1; | 	opt->max_depth = -1; | ||||||
| 	opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED; | 	opt->pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED; | ||||||
| 	color_set(opt->color_context, ""); | 	color_set(opt->color_context, ""); | ||||||
|  | @ -153,7 +152,6 @@ void grep_init(struct grep_opt *opt, const char *prefix) | ||||||
| 	opt->linenum = def->linenum; | 	opt->linenum = def->linenum; | ||||||
| 	opt->max_depth = def->max_depth; | 	opt->max_depth = def->max_depth; | ||||||
| 	opt->pathname = def->pathname; | 	opt->pathname = def->pathname; | ||||||
| 	opt->regflags = def->regflags; |  | ||||||
| 	opt->relative = def->relative; | 	opt->relative = def->relative; | ||||||
| 	opt->output = def->output; | 	opt->output = def->output; | ||||||
|  |  | ||||||
|  | @ -169,6 +167,24 @@ void grep_init(struct grep_opt *opt, const char *prefix) | ||||||
|  |  | ||||||
| static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt) | static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt) | ||||||
| { | { | ||||||
|  | 	/* | ||||||
|  | 	 * When committing to the pattern type by setting the relevant | ||||||
|  | 	 * fields in grep_opt it's generally not necessary to zero out | ||||||
|  | 	 * the fields we're not choosing, since they won't have been | ||||||
|  | 	 * set by anything. The extended_regexp_option field is the | ||||||
|  | 	 * only exception to this. | ||||||
|  | 	 * | ||||||
|  | 	 * This is because in the process of parsing grep.patternType | ||||||
|  | 	 * & grep.extendedRegexp we set opt->pattern_type_option and | ||||||
|  | 	 * opt->extended_regexp_option, respectively. We then | ||||||
|  | 	 * internally use opt->extended_regexp_option to see if we're | ||||||
|  | 	 * compiling an ERE. It must be unset if that's not actually | ||||||
|  | 	 * the case. | ||||||
|  | 	 */ | ||||||
|  | 	if (pattern_type != GREP_PATTERN_TYPE_ERE && | ||||||
|  | 	    opt->extended_regexp_option) | ||||||
|  | 		opt->extended_regexp_option = 0; | ||||||
|  |  | ||||||
| 	switch (pattern_type) { | 	switch (pattern_type) { | ||||||
| 	case GREP_PATTERN_TYPE_UNSPECIFIED: | 	case GREP_PATTERN_TYPE_UNSPECIFIED: | ||||||
| 		/* fall through */ | 		/* fall through */ | ||||||
|  | @ -177,7 +193,7 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case GREP_PATTERN_TYPE_ERE: | 	case GREP_PATTERN_TYPE_ERE: | ||||||
| 		opt->regflags |= REG_EXTENDED; | 		opt->extended_regexp_option = 1; | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case GREP_PATTERN_TYPE_FIXED: | 	case GREP_PATTERN_TYPE_FIXED: | ||||||
|  | @ -207,6 +223,11 @@ void grep_commit_pattern_type(enum grep_pattern_type pattern_type, struct grep_o | ||||||
| 	else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED) | 	else if (opt->pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED) | ||||||
| 		grep_set_pattern_type_option(opt->pattern_type_option, opt); | 		grep_set_pattern_type_option(opt->pattern_type_option, opt); | ||||||
| 	else if (opt->extended_regexp_option) | 	else if (opt->extended_regexp_option) | ||||||
|  | 		/* | ||||||
|  | 		 * This branch *must* happen after setting from the | ||||||
|  | 		 * opt->pattern_type_option above, we don't want | ||||||
|  | 		 * grep.extendedRegexp to override grep.patternType! | ||||||
|  | 		 */ | ||||||
| 		grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt); | 		grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, opt); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -572,7 +593,7 @@ static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt) | ||||||
| { | { | ||||||
| 	struct strbuf sb = STRBUF_INIT; | 	struct strbuf sb = STRBUF_INIT; | ||||||
| 	int err; | 	int err; | ||||||
| 	int regflags = opt->regflags; | 	int regflags = REG_NEWLINE; | ||||||
|  |  | ||||||
| 	basic_regex_quote_buf(&sb, p->pattern); | 	basic_regex_quote_buf(&sb, p->pattern); | ||||||
| 	if (opt->ignore_case) | 	if (opt->ignore_case) | ||||||
|  | @ -591,12 +612,12 @@ static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt) | ||||||
|  |  | ||||||
| static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) | static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) | ||||||
| { | { | ||||||
| 	int icase, ascii_only; | 	int ascii_only; | ||||||
| 	int err; | 	int err; | ||||||
|  | 	int regflags = REG_NEWLINE; | ||||||
|  |  | ||||||
| 	p->word_regexp = opt->word_regexp; | 	p->word_regexp = opt->word_regexp; | ||||||
| 	p->ignore_case = opt->ignore_case; | 	p->ignore_case = opt->ignore_case; | ||||||
| 	icase	       = opt->regflags & REG_ICASE || p->ignore_case; |  | ||||||
| 	ascii_only     = !has_non_ascii(p->pattern); | 	ascii_only     = !has_non_ascii(p->pattern); | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
|  | @ -614,10 +635,10 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) | ||||||
| 	if (opt->fixed || | 	if (opt->fixed || | ||||||
| 	    has_null(p->pattern, p->patternlen) || | 	    has_null(p->pattern, p->patternlen) || | ||||||
| 	    is_fixed(p->pattern, p->patternlen)) | 	    is_fixed(p->pattern, p->patternlen)) | ||||||
| 		p->fixed = !icase || ascii_only; | 		p->fixed = !p->ignore_case || ascii_only; | ||||||
|  |  | ||||||
| 	if (p->fixed) { | 	if (p->fixed) { | ||||||
| 		p->kws = kwsalloc(icase ? tolower_trans_tbl : NULL); | 		p->kws = kwsalloc(p->ignore_case ? tolower_trans_tbl : NULL); | ||||||
| 		kwsincr(p->kws, p->pattern, p->patternlen); | 		kwsincr(p->kws, p->pattern, p->patternlen); | ||||||
| 		kwsprep(p->kws); | 		kwsprep(p->kws); | ||||||
| 		return; | 		return; | ||||||
|  | @ -641,7 +662,11 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = regcomp(&p->regexp, p->pattern, opt->regflags); | 	if (p->ignore_case) | ||||||
|  | 		regflags |= REG_ICASE; | ||||||
|  | 	if (opt->extended_regexp_option) | ||||||
|  | 		regflags |= REG_EXTENDED; | ||||||
|  | 	err = regcomp(&p->regexp, p->pattern, regflags); | ||||||
| 	if (err) { | 	if (err) { | ||||||
| 		char errbuf[1024]; | 		char errbuf[1024]; | ||||||
| 		regerror(err, &p->regexp, errbuf, 1024); | 		regerror(err, &p->regexp, errbuf, 1024); | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								grep.h
								
								
								
								
							
							
						
						
									
										1
									
								
								grep.h
								
								
								
								
							|  | @ -162,7 +162,6 @@ struct grep_opt { | ||||||
| 	char color_match_selected[COLOR_MAXLEN]; | 	char color_match_selected[COLOR_MAXLEN]; | ||||||
| 	char color_selected[COLOR_MAXLEN]; | 	char color_selected[COLOR_MAXLEN]; | ||||||
| 	char color_sep[COLOR_MAXLEN]; | 	char color_sep[COLOR_MAXLEN]; | ||||||
| 	int regflags; |  | ||||||
| 	unsigned pre_context; | 	unsigned pre_context; | ||||||
| 	unsigned post_context; | 	unsigned post_context; | ||||||
| 	unsigned last_shown; | 	unsigned last_shown; | ||||||
|  |  | ||||||
|  | @ -1362,7 +1362,6 @@ void init_revisions(struct rev_info *revs, const char *prefix) | ||||||
| 	init_grep_defaults(); | 	init_grep_defaults(); | ||||||
| 	grep_init(&revs->grep_filter, prefix); | 	grep_init(&revs->grep_filter, prefix); | ||||||
| 	revs->grep_filter.status_only = 1; | 	revs->grep_filter.status_only = 1; | ||||||
| 	revs->grep_filter.regflags = REG_NEWLINE; |  | ||||||
|  |  | ||||||
| 	diff_setup(&revs->diffopt); | 	diff_setup(&revs->diffopt); | ||||||
| 	if (prefix && !revs->diffopt.prefix) { | 	if (prefix && !revs->diffopt.prefix) { | ||||||
|  | @ -2022,7 +2021,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg | ||||||
| 		revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE; | 		revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE; | ||||||
| 	} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { | 	} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { | ||||||
| 		revs->grep_filter.ignore_case = 1; | 		revs->grep_filter.ignore_case = 1; | ||||||
| 		revs->grep_filter.regflags |= REG_ICASE; |  | ||||||
| 		DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE); | 		DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE); | ||||||
| 	} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { | 	} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { | ||||||
| 		revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED; | 		revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Ævar Arnfjörð Bjarmason
						Ævar Arnfjörð Bjarmason