Update "perl-compatible regular expression" support to enable JIT
and also allow linking with the newer PCRE v2 library.

* ab/pcre-v2:
  grep: add support for PCRE v2
  grep: un-break building with PCRE >= 8.32 without --enable-jit
  grep: un-break building with PCRE < 8.20
  grep: un-break building with PCRE < 8.32
  grep: add support for the PCRE v1 JIT API
  log: add -P as a synonym for --perl-regexp
  grep: skip pthreads overhead when using one thread
  grep: don't redundantly compile throwaway patterns under threading
This commit is contained in:
Junio C Hamano 2017-06-19 12:38:43 -07:00
Родитель 32e0da583f 94da9193a6
Коммит ae7e4d4fed
10 изменённых файлов: 350 добавлений и 30 удалений

Просмотреть файл

@ -91,6 +91,7 @@ endif::git-rev-list[]
Consider the limiting patterns to be fixed strings (don't interpret
pattern as a regular expression).
-P::
--perl-regexp::
Consider the limiting patterns to be Perl-compatible regular
expressions.

Просмотреть файл

@ -29,8 +29,23 @@ all::
# Perl-compatible regular expressions instead of standard or extended
# POSIX regular expressions.
#
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
# default in future releases.
#
# When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
# library is compiled without --enable-jit. We will auto-detect
# whether the version of the PCRE v1 library in use has JIT support at
# all, but we unfortunately can't auto-detect whether JIT support
# hasn't been compiled in in an otherwise JIT-supporting version. If
# you have link-time errors about a missing `pcre_jit_exec` define
# this, or recompile PCRE v1 with --enable-jit.
#
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
# in /foo/bar/include and /foo/bar/lib directories. Which version of
# PCRE this points to determined by the USE_LIBPCRE1 and USE_LIBPCRE2
# variables.
#
# Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
#
@ -1089,13 +1104,29 @@ ifdef NO_LIBGEN_H
COMPAT_OBJS += compat/basename.o
endif
ifdef USE_LIBPCRE
BASIC_CFLAGS += -DUSE_LIBPCRE1
ifdef LIBPCREDIR
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
USE_LIBPCRE1 ?= $(USE_LIBPCRE)
ifneq (,$(USE_LIBPCRE1))
ifdef USE_LIBPCRE2
$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
endif
BASIC_CFLAGS += -DUSE_LIBPCRE1
EXTLIBS += -lpcre
ifdef NO_LIBPCRE1_JIT
BASIC_CFLAGS += -DNO_LIBPCRE1_JIT
endif
endif
ifdef USE_LIBPCRE2
BASIC_CFLAGS += -DUSE_LIBPCRE2
EXTLIBS += -lpcre2-8
endif
ifdef LIBPCREDIR
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
endif
ifdef HAVE_ALLOCA_H
@ -2249,7 +2280,9 @@ GIT-BUILD-OPTIONS: FORCE
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
@echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE1)))'\' >>$@+
@echo USE_LIBPCRE2=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE2)))'\' >>$@+
@echo NO_LIBPCRE1_JIT=\''$(subst ','\'',$(subst ','\'',$(NO_LIBPCRE1_JIT)))'\' >>$@+
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
@echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+

Просмотреть файл

@ -224,7 +224,8 @@ static void start_threads(struct grep_opt *opt)
int err;
struct grep_opt *o = grep_opt_dup(opt);
o->output = strbuf_out;
o->debug = 0;
if (i)
o->debug = 0;
compile_grep_patterns(o);
err = pthread_create(&threads[i], NULL, run, o);
@ -1170,8 +1171,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (!opt.fixed && opt.ignore_case)
opt.regflags |= REG_ICASE;
compile_grep_patterns(&opt);
/*
* We have to find "--" in a separate pass, because its presence
* influences how we will parse arguments that come before it.
@ -1244,12 +1243,23 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
num_threads = GREP_NUM_THREADS_DEFAULT;
else if (num_threads < 0)
die(_("invalid number of threads specified (%d)"), num_threads);
if (num_threads == 1)
num_threads = 0;
#else
if (num_threads)
warning(_("no threads support, ignoring --threads"));
num_threads = 0;
#endif
if (!num_threads)
/*
* The compiled patterns on the main path are only
* used when not using threading. Otherwise
* start_threads() below calls compile_grep_patterns()
* for each thread.
*/
compile_grep_patterns(&opt);
#ifndef NO_PTHREADS
if (num_threads) {
if (!(opt.name_only || opt.unmatch_name_only || opt.count)

Просмотреть файл

@ -555,6 +555,7 @@ else
NO_GETTEXT =
USE_GETTEXT_SCHEME = fallthrough
USE_LIBPCRE= YesPlease
NO_LIBPCRE1_JIT = UnfortunatelyYes
NO_CURL =
USE_NED_ALLOCATOR = YesPlease
else

Просмотреть файл

@ -255,21 +255,61 @@ GIT_PARSE_WITH([openssl]))
# Perl-compatible regular expressions instead of standard or extended
# POSIX regular expressions.
#
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
# default in future releases.
#
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
#
AC_ARG_WITH(libpcre,
AS_HELP_STRING([--with-libpcre],[support Perl-compatible regexes (default is NO)])
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
AS_HELP_STRING([--with-libpcre],[synonym for --with-libpcre1]),
if test "$withval" = "no"; then
USE_LIBPCRE=
USE_LIBPCRE1=
elif test "$withval" = "yes"; then
USE_LIBPCRE=YesPlease
USE_LIBPCRE1=YesPlease
else
USE_LIBPCRE=YesPlease
USE_LIBPCRE1=YesPlease
LIBPCREDIR=$withval
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
dnl USE_LIBPCRE can still be modified below, so don't substitute
dnl USE_LIBPCRE1 can still be modified below, so don't substitute
dnl it yet.
GIT_CONF_SUBST([LIBPCREDIR])
fi)
AC_ARG_WITH(libpcre1,
AS_HELP_STRING([--with-libpcre1],[support Perl-compatible regexes via libpcre1 (default is NO)])
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
if test "$withval" = "no"; then
USE_LIBPCRE1=
elif test "$withval" = "yes"; then
USE_LIBPCRE1=YesPlease
else
USE_LIBPCRE1=YesPlease
LIBPCREDIR=$withval
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
dnl USE_LIBPCRE1 can still be modified below, so don't substitute
dnl it yet.
GIT_CONF_SUBST([LIBPCREDIR])
fi)
AC_ARG_WITH(libpcre2,
AS_HELP_STRING([--with-libpcre2],[support Perl-compatible regexes via libpcre2 (default is NO)])
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
if test -n "$USE_LIBPCRE1"; then
AC_MSG_ERROR([Only supply one of --with-libpcre1 or --with-libpcre2!])
fi
if test "$withval" = "no"; then
USE_LIBPCRE2=
elif test "$withval" = "yes"; then
USE_LIBPCRE2=YesPlease
else
USE_LIBPCRE2=YesPlease
LIBPCREDIR=$withval
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
dnl USE_LIBPCRE2 can still be modified below, so don't substitute
dnl it yet.
GIT_CONF_SUBST([LIBPCREDIR])
fi)
@ -501,13 +541,11 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
GIT_CONF_SUBST([NO_OPENSSL])
#
# Define USE_LIBPCRE if you have and want to use libpcre. Various
# commands such as log and grep offer runtime options to use
# Perl-compatible regular expressions instead of standard or extended
# POSIX regular expressions.
# Handle the USE_LIBPCRE1 and USE_LIBPCRE2 options potentially set
# above.
#
if test -n "$USE_LIBPCRE"; then
if test -n "$USE_LIBPCRE1"; then
GIT_STASH_FLAGS($LIBPCREDIR)
@ -517,7 +555,22 @@ AC_CHECK_LIB([pcre], [pcre_version],
GIT_UNSTASH_FLAGS($LIBPCREDIR)
GIT_CONF_SUBST([USE_LIBPCRE])
GIT_CONF_SUBST([USE_LIBPCRE1])
fi
if test -n "$USE_LIBPCRE2"; then
GIT_STASH_FLAGS($LIBPCREDIR)
AC_CHECK_LIB([pcre2-8], [pcre2_config_8],
[USE_LIBPCRE2=YesPlease],
[USE_LIBPCRE2=])
GIT_UNSTASH_FLAGS($LIBPCREDIR)
GIT_CONF_SUBST([USE_LIBPCRE2])
fi

185
grep.c
Просмотреть файл

@ -179,22 +179,37 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
case GREP_PATTERN_TYPE_BRE:
opt->fixed = 0;
opt->pcre1 = 0;
opt->pcre2 = 0;
break;
case GREP_PATTERN_TYPE_ERE:
opt->fixed = 0;
opt->pcre1 = 0;
opt->pcre2 = 0;
opt->regflags |= REG_EXTENDED;
break;
case GREP_PATTERN_TYPE_FIXED:
opt->fixed = 1;
opt->pcre1 = 0;
opt->pcre2 = 0;
break;
case GREP_PATTERN_TYPE_PCRE:
opt->fixed = 0;
#ifdef USE_LIBPCRE2
opt->pcre1 = 0;
opt->pcre2 = 1;
#else
/*
* It's important that pcre1 always be assigned to
* even when there's no USE_LIBPCRE* defined. We still
* call the PCRE stub function, it just dies with
* "cannot use Perl-compatible regexes[...]".
*/
opt->pcre1 = 1;
opt->pcre2 = 0;
#endif
break;
}
}
@ -365,9 +380,22 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
if (!p->pcre1_regexp)
compile_regexp_failed(p, error);
p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error);
if (!p->pcre1_extra_info && error)
die("%s", error);
#ifdef GIT_PCRE1_USE_JIT
pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on);
if (p->pcre1_jit_on == 1) {
p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
if (!p->pcre1_jit_stack)
die("Couldn't allocate PCRE JIT stack");
pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
} else if (p->pcre1_jit_on != 0) {
die("BUG: The pcre1_jit_on variable should be 0 or 1, not %d",
p->pcre1_jit_on);
}
#endif
}
static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
@ -378,8 +406,19 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
if (eflags & REG_NOTBOL)
flags |= PCRE_NOTBOL;
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
0, flags, ovector, ARRAY_SIZE(ovector));
#ifdef GIT_PCRE1_USE_JIT
if (p->pcre1_jit_on) {
ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
eol - line, 0, flags, ovector,
ARRAY_SIZE(ovector), p->pcre1_jit_stack);
} else
#endif
{
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
eol - line, 0, flags, ovector,
ARRAY_SIZE(ovector));
}
if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
die("pcre_exec failed with error code %d", ret);
if (ret > 0) {
@ -394,7 +433,15 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
static void free_pcre1_regexp(struct grep_pat *p)
{
pcre_free(p->pcre1_regexp);
pcre_free(p->pcre1_extra_info);
#ifdef GIT_PCRE1_USE_JIT
if (p->pcre1_jit_on) {
pcre_free_study(p->pcre1_extra_info);
pcre_jit_stack_free(p->pcre1_jit_stack);
} else
#endif
{
pcre_free(p->pcre1_extra_info);
}
pcre_free((void *)p->pcre1_tables);
}
#else /* !USE_LIBPCRE1 */
@ -414,6 +461,127 @@ static void free_pcre1_regexp(struct grep_pat *p)
}
#endif /* !USE_LIBPCRE1 */
#ifdef USE_LIBPCRE2
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
{
int error;
PCRE2_UCHAR errbuf[256];
PCRE2_SIZE erroffset;
int options = PCRE2_MULTILINE;
const uint8_t *character_tables = NULL;
int jitret;
assert(opt->pcre2);
p->pcre2_compile_context = NULL;
if (opt->ignore_case) {
if (has_non_ascii(p->pattern)) {
character_tables = pcre2_maketables(NULL);
p->pcre2_compile_context = pcre2_compile_context_create(NULL);
pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
}
options |= PCRE2_CASELESS;
}
if (is_utf8_locale() && has_non_ascii(p->pattern))
options |= PCRE2_UTF;
p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
p->patternlen, options, &error, &erroffset,
p->pcre2_compile_context);
if (p->pcre2_pattern) {
p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
if (!p->pcre2_match_data)
die("Couldn't allocate PCRE2 match data");
} else {
pcre2_get_error_message(error, errbuf, sizeof(errbuf));
compile_regexp_failed(p, (const char *)&errbuf);
}
pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on);
if (p->pcre2_jit_on == 1) {
jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE);
if (jitret)
die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret);
p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
if (!p->pcre2_jit_stack)
die("Couldn't allocate PCRE2 JIT stack");
p->pcre2_match_context = pcre2_match_context_create(NULL);
if (!p->pcre2_jit_stack)
die("Couldn't allocate PCRE2 match context");
pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
} else if (p->pcre2_jit_on != 0) {
die("BUG: The pcre2_jit_on variable should be 0 or 1, not %d",
p->pcre1_jit_on);
}
}
static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
regmatch_t *match, int eflags)
{
int ret, flags = 0;
PCRE2_SIZE *ovector;
PCRE2_UCHAR errbuf[256];
if (eflags & REG_NOTBOL)
flags |= PCRE2_NOTBOL;
if (p->pcre2_jit_on)
ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line,
eol - line, 0, flags, p->pcre2_match_data,
NULL);
else
ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line,
eol - line, 0, flags, p->pcre2_match_data,
NULL);
if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) {
pcre2_get_error_message(ret, errbuf, sizeof(errbuf));
die("%s failed with error code %d: %s",
(p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret,
errbuf);
}
if (ret > 0) {
ovector = pcre2_get_ovector_pointer(p->pcre2_match_data);
ret = 0;
match->rm_so = (int)ovector[0];
match->rm_eo = (int)ovector[1];
}
return ret;
}
static void free_pcre2_pattern(struct grep_pat *p)
{
pcre2_compile_context_free(p->pcre2_compile_context);
pcre2_code_free(p->pcre2_pattern);
pcre2_match_data_free(p->pcre2_match_data);
pcre2_jit_stack_free(p->pcre2_jit_stack);
pcre2_match_context_free(p->pcre2_match_context);
}
#else /* !USE_LIBPCRE2 */
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
{
/*
* Unreachable until USE_LIBPCRE2 becomes synonymous with
* USE_LIBPCRE. See the sibling comment in
* grep_set_pattern_type_option().
*/
die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
}
static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
regmatch_t *match, int eflags)
{
return 1;
}
static void free_pcre2_pattern(struct grep_pat *p)
{
}
#endif /* !USE_LIBPCRE2 */
static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
{
struct strbuf sb = STRBUF_INIT;
@ -479,6 +647,11 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
return;
}
if (opt->pcre2) {
compile_pcre2_pattern(p, opt);
return;
}
if (opt->pcre1) {
compile_pcre1_regexp(p, opt);
return;
@ -838,6 +1011,8 @@ void free_grep_patterns(struct grep_opt *opt)
kwsfree(p->kws);
else if (p->pcre1_regexp)
free_pcre1_regexp(p);
else if (p->pcre2_pattern)
free_pcre2_pattern(p);
else
regfree(&p->regexp);
free(p->pattern);
@ -918,6 +1093,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
hit = !fixmatch(p, line, eol, match);
else if (p->pcre1_regexp)
hit = !pcre1match(p, line, eol, match, eflags);
else if (p->pcre2_pattern)
hit = !pcre2match(p, line, eol, match, eflags);
else
hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
eflags);

33
grep.h
Просмотреть файл

@ -3,9 +3,33 @@
#include "color.h"
#ifdef USE_LIBPCRE1
#include <pcre.h>
#ifdef PCRE_CONFIG_JIT
#if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
#ifndef NO_LIBPCRE1_JIT
#define GIT_PCRE1_USE_JIT
#endif
#endif
#endif
#ifndef PCRE_STUDY_JIT_COMPILE
#define PCRE_STUDY_JIT_COMPILE 0
#endif
#if PCRE_MAJOR <= 8 && PCRE_MINOR < 20
typedef int pcre_jit_stack;
#endif
#else
typedef int pcre;
typedef int pcre_extra;
typedef int pcre_jit_stack;
#endif
#ifdef USE_LIBPCRE2
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#else
typedef int pcre2_code;
typedef int pcre2_match_data;
typedef int pcre2_compile_context;
typedef int pcre2_match_context;
typedef int pcre2_jit_stack;
#endif
#include "kwset.h"
#include "thread-utils.h"
@ -48,7 +72,15 @@ struct grep_pat {
regex_t regexp;
pcre *pcre1_regexp;
pcre_extra *pcre1_extra_info;
pcre_jit_stack *pcre1_jit_stack;
const unsigned char *pcre1_tables;
int pcre1_jit_on;
pcre2_code *pcre2_pattern;
pcre2_match_data *pcre2_match_data;
pcre2_compile_context *pcre2_compile_context;
pcre2_match_context *pcre2_match_context;
pcre2_jit_stack *pcre2_jit_stack;
uint32_t pcre2_jit_on;
kwset_t kws;
unsigned fixed:1;
unsigned ignore_case:1;
@ -112,6 +144,7 @@ struct grep_opt {
int extended;
int use_reflog_filter;
int pcre1;
int pcre2;
int relative;
int pathname;
int null_following_name;

Просмотреть файл

@ -2031,7 +2031,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;
} else if (!strcmp(arg, "--perl-regexp")) {
} else if (!strcmp(arg, "--perl-regexp") || !strcmp(arg, "-P")) {
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_PCRE;
} else if (!strcmp(arg, "--all-match")) {
revs->grep_filter.all_match = 1;

Просмотреть файл

@ -404,8 +404,20 @@ test_expect_success 'log with various grep.patternType configurations & command-
--grep="(1|2)" >actual.fixed.short-arg &&
git log --pretty=tformat:%s -E \
--grep="\|2" >actual.extended.short-arg &&
if test_have_prereq PCRE
then
git log --pretty=tformat:%s -P \
--grep="[\d]\|" >actual.perl.short-arg
else
test_must_fail git log -P \
--grep="[\d]\|"
fi &&
test_cmp expect.fixed actual.fixed.short-arg &&
test_cmp expect.extended actual.extended.short-arg &&
if test_have_prereq PCRE
then
test_cmp expect.perl actual.perl.short-arg
fi &&
git log --pretty=tformat:%s --fixed-strings \
--grep="(1|2)" >actual.fixed.long-arg &&

Просмотреть файл

@ -1020,7 +1020,7 @@ esac
test -z "$NO_PERL" && test_set_prereq PERL
test -z "$NO_PTHREADS" && test_set_prereq PTHREADS
test -z "$NO_PYTHON" && test_set_prereq PYTHON
test -n "$USE_LIBPCRE1" && test_set_prereq PCRE
test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
# Can we rely on git's output in the C locale?