Skip to content

Commit 36dcb57

Browse files
committed
Merge branch 'ab/grep-preparatory-cleanup'
The internal implementation of "git grep" has seen some clean-up. * ab/grep-preparatory-cleanup: (31 commits) grep: assert that threading is enabled when calling grep_{lock,unlock} grep: given --threads with NO_PTHREADS=YesPlease, warn pack-objects: fix buggy warning about threads pack-objects & index-pack: add test for --threads warning test-lib: add a PTHREADS prerequisite grep: move is_fixed() earlier to avoid forward declaration grep: change internal *pcre* variable & function names to be *pcre1* grep: change the internal PCRE macro names to be PCRE1 grep: factor test for \0 in grep patterns into a function grep: remove redundant regflags assignments grep: catch a missing enum in switch statement perf: add a comparison test of log --grep regex engines with -F perf: add a comparison test of log --grep regex engines perf: add a comparison test of grep regex engines with -F perf: add a comparison test of grep regex engines perf: emit progress output when unpacking & building perf: add a GIT_PERF_MAKE_COMMAND for when *_MAKE_OPTS won't do grep: add tests to fix blind spots with \0 patterns grep: prepare for testing binary regexes containing rx metacharacters grep: add a test helper function for less verbose -f \0 tests ...
2 parents 7ef0d04 + 8df4c29 commit 36dcb57

24 files changed

+843
-239
lines changed

Documentation/git-grep.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,11 @@ OPTIONS
161161

162162
-P::
163163
--perl-regexp::
164-
Use Perl-compatible regexp for patterns. Requires libpcre to be
165-
compiled in.
164+
Use Perl-compatible regular expressions for patterns.
165+
+
166+
Support for these types of regular expressions is an optional
167+
compile-time dependency. If Git wasn't compiled with support for them
168+
providing this option will cause it to die.
166169

167170
-F::
168171
--fixed-strings::

Documentation/rev-list-options.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,12 @@ endif::git-rev-list[]
9292
pattern as a regular expression).
9393

9494
--perl-regexp::
95-
Consider the limiting patterns to be Perl-compatible regular expressions.
96-
Requires libpcre to be compiled in.
95+
Consider the limiting patterns to be Perl-compatible regular
96+
expressions.
97+
+
98+
Support for these types of regular expressions is an optional
99+
compile-time dependency. If Git wasn't compiled with support for them
100+
providing this option will cause it to die.
97101

98102
--remove-empty::
99103
Stop when a given path disappears from the tree.

Makefile

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ all::
2424
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
2525
# This also implies BLK_SHA1.
2626
#
27-
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
28-
# able to use Perl-compatible regular expressions.
27+
# Define USE_LIBPCRE if you have and want to use libpcre. Various
28+
# commands such as log and grep offer runtime options to use
29+
# Perl-compatible regular expressions instead of standard or extended
30+
# POSIX regular expressions.
2931
#
3032
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
3133
# /foo/bar/include and /foo/bar/lib directories.
@@ -1087,7 +1089,7 @@ ifdef NO_LIBGEN_H
10871089
endif
10881090

10891091
ifdef USE_LIBPCRE
1090-
BASIC_CFLAGS += -DUSE_LIBPCRE
1092+
BASIC_CFLAGS += -DUSE_LIBPCRE1
10911093
ifdef LIBPCREDIR
10921094
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
10931095
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
@@ -2239,8 +2241,9 @@ GIT-BUILD-OPTIONS: FORCE
22392241
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
22402242
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
22412243
@echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+
2242-
@echo USE_LIBPCRE=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
2244+
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
22432245
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
2246+
@echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
22442247
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
22452248
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
22462249
@echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
@@ -2271,6 +2274,9 @@ endif
22712274
ifdef GIT_PERF_MAKE_OPTS
22722275
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@+
22732276
endif
2277+
ifdef GIT_PERF_MAKE_COMMAND
2278+
@echo GIT_PERF_MAKE_COMMAND=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_COMMAND)))'\' >>$@+
2279+
endif
22742280
ifdef GIT_INTEROP_MAKE_OPTS
22752281
@echo GIT_INTEROP_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_INTEROP_MAKE_OPTS)))'\' >>$@+
22762282
endif

builtin/grep.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ static pthread_mutex_t grep_mutex;
7373

7474
static inline void grep_lock(void)
7575
{
76-
if (num_threads)
77-
pthread_mutex_lock(&grep_mutex);
76+
assert(num_threads);
77+
pthread_mutex_lock(&grep_mutex);
7878
}
7979

8080
static inline void grep_unlock(void)
8181
{
82-
if (num_threads)
83-
pthread_mutex_unlock(&grep_mutex);
82+
assert(num_threads);
83+
pthread_mutex_unlock(&grep_mutex);
8484
}
8585

8686
/* Signalled when a new work_item is added to todo. */
@@ -289,6 +289,17 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
289289
if (num_threads < 0)
290290
die(_("invalid number of threads specified (%d) for %s"),
291291
num_threads, var);
292+
#ifdef NO_PTHREADS
293+
else if (num_threads && num_threads != 1) {
294+
/*
295+
* TRANSLATORS: %s is the configuration
296+
* variable for tweaking threads, currently
297+
* grep.threads
298+
*/
299+
warning(_("no threads support, ignoring %s"), var);
300+
num_threads = 0;
301+
}
302+
#endif
292303
}
293304

294305
return st;
@@ -495,6 +506,8 @@ static void compile_submodule_options(const struct grep_opt *opt,
495506
break;
496507
case GREP_PATTERN_TYPE_UNSPECIFIED:
497508
break;
509+
default:
510+
die("BUG: Added a new grep pattern type without updating switch statement");
498511
}
499512

500513
for (pattern = opt->pattern_list; pattern != NULL;
@@ -1229,6 +1242,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
12291242
else if (num_threads < 0)
12301243
die(_("invalid number of threads specified (%d)"), num_threads);
12311244
#else
1245+
if (num_threads)
1246+
warning(_("no threads support, ignoring --threads"));
12321247
num_threads = 0;
12331248
#endif
12341249

builtin/pack-objects.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2483,8 +2483,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
24832483
die("invalid number of threads specified (%d)",
24842484
delta_search_threads);
24852485
#ifdef NO_PTHREADS
2486-
if (delta_search_threads != 1)
2486+
if (delta_search_threads != 1) {
24872487
warning("no threads support, ignoring %s", k);
2488+
delta_search_threads = 0;
2489+
}
24882490
#endif
24892491
return 0;
24902492
}

configure.ac

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,10 @@ AS_HELP_STRING([--with-openssl],[use OpenSSL library (default is YES)])
250250
AS_HELP_STRING([], [ARG can be prefix for openssl library and headers]),
251251
GIT_PARSE_WITH([openssl]))
252252

253-
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
254-
# able to use Perl-compatible regular expressions.
253+
# Define USE_LIBPCRE if you have and want to use libpcre. Various
254+
# commands such as log and grep offer runtime options to use
255+
# Perl-compatible regular expressions instead of standard or extended
256+
# POSIX regular expressions.
255257
#
256258
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
257259
# /foo/bar/include and /foo/bar/lib directories.
@@ -499,8 +501,10 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
499501
GIT_CONF_SUBST([NO_OPENSSL])
500502

501503
#
502-
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
503-
# able to use Perl-compatible regular expressions.
504+
# Define USE_LIBPCRE if you have and want to use libpcre. Various
505+
# commands such as log and grep offer runtime options to use
506+
# Perl-compatible regular expressions instead of standard or extended
507+
# POSIX regular expressions.
504508
#
505509

506510
if test -n "$USE_LIBPCRE"; then

grep.c

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -178,26 +178,23 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
178178

179179
case GREP_PATTERN_TYPE_BRE:
180180
opt->fixed = 0;
181-
opt->pcre = 0;
182-
opt->regflags &= ~REG_EXTENDED;
181+
opt->pcre1 = 0;
183182
break;
184183

185184
case GREP_PATTERN_TYPE_ERE:
186185
opt->fixed = 0;
187-
opt->pcre = 0;
186+
opt->pcre1 = 0;
188187
opt->regflags |= REG_EXTENDED;
189188
break;
190189

191190
case GREP_PATTERN_TYPE_FIXED:
192191
opt->fixed = 1;
193-
opt->pcre = 0;
194-
opt->regflags &= ~REG_EXTENDED;
192+
opt->pcre1 = 0;
195193
break;
196194

197195
case GREP_PATTERN_TYPE_PCRE:
198196
opt->fixed = 0;
199-
opt->pcre = 1;
200-
opt->regflags &= ~REG_EXTENDED;
197+
opt->pcre1 = 1;
201198
break;
202199
}
203200
}
@@ -324,40 +321,64 @@ static NORETURN void compile_regexp_failed(const struct grep_pat *p,
324321
die("%s'%s': %s", where, p->pattern, error);
325322
}
326323

327-
#ifdef USE_LIBPCRE
328-
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
324+
static int is_fixed(const char *s, size_t len)
325+
{
326+
size_t i;
327+
328+
for (i = 0; i < len; i++) {
329+
if (is_regex_special(s[i]))
330+
return 0;
331+
}
332+
333+
return 1;
334+
}
335+
336+
static int has_null(const char *s, size_t len)
337+
{
338+
/*
339+
* regcomp cannot accept patterns with NULs so when using it
340+
* we consider any pattern containing a NUL fixed.
341+
*/
342+
if (memchr(s, 0, len))
343+
return 1;
344+
345+
return 0;
346+
}
347+
348+
#ifdef USE_LIBPCRE1
349+
static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
329350
{
330351
const char *error;
331352
int erroffset;
332353
int options = PCRE_MULTILINE;
333354

334355
if (opt->ignore_case) {
335356
if (has_non_ascii(p->pattern))
336-
p->pcre_tables = pcre_maketables();
357+
p->pcre1_tables = pcre_maketables();
337358
options |= PCRE_CASELESS;
338359
}
339360
if (is_utf8_locale() && has_non_ascii(p->pattern))
340361
options |= PCRE_UTF8;
341362

342-
p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
343-
p->pcre_tables);
344-
if (!p->pcre_regexp)
363+
p->pcre1_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
364+
p->pcre1_tables);
365+
if (!p->pcre1_regexp)
345366
compile_regexp_failed(p, error);
346367

347-
p->pcre_extra_info = pcre_study(p->pcre_regexp, 0, &error);
348-
if (!p->pcre_extra_info && error)
368+
p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
369+
if (!p->pcre1_extra_info && error)
349370
die("%s", error);
350371
}
351372

352-
static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
373+
static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
353374
regmatch_t *match, int eflags)
354375
{
355376
int ovector[30], ret, flags = 0;
356377

357378
if (eflags & REG_NOTBOL)
358379
flags |= PCRE_NOTBOL;
359380

360-
ret = pcre_exec(p->pcre_regexp, p->pcre_extra_info, line, eol - line,
381+
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
361382
0, flags, ovector, ARRAY_SIZE(ovector));
362383
if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
363384
die("pcre_exec failed with error code %d", ret);
@@ -370,55 +391,36 @@ static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
370391
return ret;
371392
}
372393

373-
static void free_pcre_regexp(struct grep_pat *p)
394+
static void free_pcre1_regexp(struct grep_pat *p)
374395
{
375-
pcre_free(p->pcre_regexp);
376-
pcre_free(p->pcre_extra_info);
377-
pcre_free((void *)p->pcre_tables);
396+
pcre_free(p->pcre1_regexp);
397+
pcre_free(p->pcre1_extra_info);
398+
pcre_free((void *)p->pcre1_tables);
378399
}
379-
#else /* !USE_LIBPCRE */
380-
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
400+
#else /* !USE_LIBPCRE1 */
401+
static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
381402
{
382403
die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
383404
}
384405

385-
static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
406+
static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
386407
regmatch_t *match, int eflags)
387408
{
388409
return 1;
389410
}
390411

391-
static void free_pcre_regexp(struct grep_pat *p)
412+
static void free_pcre1_regexp(struct grep_pat *p)
392413
{
393414
}
394-
#endif /* !USE_LIBPCRE */
395-
396-
static int is_fixed(const char *s, size_t len)
397-
{
398-
size_t i;
399-
400-
/* regcomp cannot accept patterns with NULs so we
401-
* consider any pattern containing a NUL fixed.
402-
*/
403-
if (memchr(s, 0, len))
404-
return 1;
405-
406-
for (i = 0; i < len; i++) {
407-
if (is_regex_special(s[i]))
408-
return 0;
409-
}
410-
411-
return 1;
412-
}
415+
#endif /* !USE_LIBPCRE1 */
413416

414417
static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
415418
{
416419
struct strbuf sb = STRBUF_INIT;
417420
int err;
418-
int regflags;
421+
int regflags = opt->regflags;
419422

420423
basic_regex_quote_buf(&sb, p->pattern);
421-
regflags = opt->regflags & ~REG_EXTENDED;
422424
if (opt->ignore_case)
423425
regflags |= REG_ICASE;
424426
err = regcomp(&p->regexp, sb.buf, regflags);
@@ -455,7 +457,9 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
455457
* simple string match using kws. p->fixed tells us if we
456458
* want to use kws.
457459
*/
458-
if (opt->fixed || is_fixed(p->pattern, p->patternlen))
460+
if (opt->fixed ||
461+
has_null(p->pattern, p->patternlen) ||
462+
is_fixed(p->pattern, p->patternlen))
459463
p->fixed = !icase || ascii_only;
460464
else
461465
p->fixed = 0;
@@ -475,8 +479,8 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
475479
return;
476480
}
477481

478-
if (opt->pcre) {
479-
compile_pcre_regexp(p, opt);
482+
if (opt->pcre1) {
483+
compile_pcre1_regexp(p, opt);
480484
return;
481485
}
482486

@@ -832,8 +836,8 @@ void free_grep_patterns(struct grep_opt *opt)
832836
case GREP_PATTERN_BODY:
833837
if (p->kws)
834838
kwsfree(p->kws);
835-
else if (p->pcre_regexp)
836-
free_pcre_regexp(p);
839+
else if (p->pcre1_regexp)
840+
free_pcre1_regexp(p);
837841
else
838842
regfree(&p->regexp);
839843
free(p->pattern);
@@ -912,8 +916,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
912916

913917
if (p->fixed)
914918
hit = !fixmatch(p, line, eol, match);
915-
else if (p->pcre_regexp)
916-
hit = !pcrematch(p, line, eol, match, eflags);
919+
else if (p->pcre1_regexp)
920+
hit = !pcre1match(p, line, eol, match, eflags);
917921
else
918922
hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
919923
eflags);

0 commit comments

Comments
 (0)