Merge branch 'ab/grep-preparatory-cleanup' into sb/submodule-blanket-recursive
authorJunio C Hamano <gitster@pobox.com>
Tue, 30 May 2017 05:27:37 +0000 (14:27 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 30 May 2017 05:28:41 +0000 (14:28 +0900)
* 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
...

24 files changed:
Documentation/git-grep.txt
Documentation/rev-list-options.txt
Makefile
builtin/grep.c
builtin/pack-objects.c
configure.ac
grep.c
grep.h
revision.c
t/README
t/perf/README
t/perf/p4220-log-grep-engines.sh [new file with mode: 0755]
t/perf/p4221-log-grep-engines-fixed.sh [new file with mode: 0755]
t/perf/p7820-grep-engines.sh [new file with mode: 0755]
t/perf/p7821-grep-engines-fixed.sh [new file with mode: 0755]
t/perf/run
t/t4202-log.sh
t/t5300-pack-object.sh
t/t7008-grep-binary.sh
t/t7810-grep.sh
t/t7812-grep-icase-non-ascii.sh
t/t7813-grep-icase-iso.sh
t/t7814-grep-recurse-submodules.sh
t/test-lib.sh
index 71f32f35089241bc452cfdccdc6b3e9a30f95366..5033483db496286910dd24507f3374e18ff6c2b5 100644 (file)
@@ -161,8 +161,11 @@ OPTIONS
 
 -P::
 --perl-regexp::
-       Use Perl-compatible regexp for patterns. Requires libpcre to be
-       compiled in.
+       Use Perl-compatible regular expressions for patterns.
++
+Support for these types of regular expressions is an optional
+compile-time dependency. If Git wasn't compiled with support for them
+providing this option will cause it to die.
 
 -F::
 --fixed-strings::
index a02f7324c01ee5811441d2a6dcb93aafd892298c..a46f70c2b16c2c03f47ccb3444cffb491b68ed83 100644 (file)
@@ -92,8 +92,12 @@ endif::git-rev-list[]
        pattern as a regular expression).
 
 --perl-regexp::
-       Consider the limiting patterns to be Perl-compatible regular expressions.
-       Requires libpcre to be compiled in.
+       Consider the limiting patterns to be Perl-compatible regular
+       expressions.
++
+Support for these types of regular expressions is an optional
+compile-time dependency. If Git wasn't compiled with support for them
+providing this option will cause it to die.
 
 --remove-empty::
        Stop when a given path disappears from the tree.
index e35542e63181144397053bf7932fad2cf97027bb..a79274e5e69c9a189f6d5a4ee857fedd93a5150d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,8 +24,10 @@ all::
 # Define NO_OPENSSL environment variable if you do not have OpenSSL.
 # This also implies BLK_SHA1.
 #
-# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
-# able to use Perl-compatible regular expressions.
+# 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.
 #
 # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
 # /foo/bar/include and /foo/bar/lib directories.
@@ -1086,7 +1088,7 @@ ifdef NO_LIBGEN_H
 endif
 
 ifdef USE_LIBPCRE
-       BASIC_CFLAGS += -DUSE_LIBPCRE
+       BASIC_CFLAGS += -DUSE_LIBPCRE1
        ifdef LIBPCREDIR
                BASIC_CFLAGS += -I$(LIBPCREDIR)/include
                EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
@@ -2238,8 +2240,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_LIBPCRE=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
+       @echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
        @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
+       @echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
        @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
        @echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
        @echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
@@ -2270,6 +2273,9 @@ endif
 ifdef GIT_PERF_MAKE_OPTS
        @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@+
 endif
+ifdef GIT_PERF_MAKE_COMMAND
+       @echo GIT_PERF_MAKE_COMMAND=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_COMMAND)))'\' >>$@+
+endif
 ifdef GIT_INTEROP_MAKE_OPTS
        @echo GIT_INTEROP_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_INTEROP_MAKE_OPTS)))'\' >>$@+
 endif
index 3ffb5b4e8176bbcd1ecf2e4ae2dc84aee968cd22..b1095362fbf9a4726367b96e0f34d38faf27d9bd 100644 (file)
@@ -73,14 +73,14 @@ static pthread_mutex_t grep_mutex;
 
 static inline void grep_lock(void)
 {
-       if (num_threads)
-               pthread_mutex_lock(&grep_mutex);
+       assert(num_threads);
+       pthread_mutex_lock(&grep_mutex);
 }
 
 static inline void grep_unlock(void)
 {
-       if (num_threads)
-               pthread_mutex_unlock(&grep_mutex);
+       assert(num_threads);
+       pthread_mutex_unlock(&grep_mutex);
 }
 
 /* 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)
                if (num_threads < 0)
                        die(_("invalid number of threads specified (%d) for %s"),
                            num_threads, var);
+#ifdef NO_PTHREADS
+               else if (num_threads && num_threads != 1) {
+                       /*
+                        * TRANSLATORS: %s is the configuration
+                        * variable for tweaking threads, currently
+                        * grep.threads
+                        */
+                       warning(_("no threads support, ignoring %s"), var);
+                       num_threads = 0;
+               }
+#endif
        }
 
        return st;
@@ -495,6 +506,8 @@ static void compile_submodule_options(const struct grep_opt *opt,
                break;
        case GREP_PATTERN_TYPE_UNSPECIFIED:
                break;
+       default:
+               die("BUG: Added a new grep pattern type without updating switch statement");
        }
 
        for (pattern = opt->pattern_list; pattern != NULL;
@@ -1227,6 +1240,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        else if (num_threads < 0)
                die(_("invalid number of threads specified (%d)"), num_threads);
 #else
+       if (num_threads)
+               warning(_("no threads support, ignoring --threads"));
        num_threads = 0;
 #endif
 
index 9b4ba8a80d7f0ac160467138507358f164b7af3e..efa21a15dd939075af0525dcd7e6646ac453999a 100644 (file)
@@ -2472,8 +2472,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                        die("invalid number of threads specified (%d)",
                            delta_search_threads);
 #ifdef NO_PTHREADS
-               if (delta_search_threads != 1)
+               if (delta_search_threads != 1) {
                        warning("no threads support, ignoring %s", k);
+                       delta_search_threads = 0;
+               }
 #endif
                return 0;
        }
index 128165529fd70ac889ed0fb5098e4290893b593d..deeb968daa07355b729d178644c843c7a0ed62c5 100644 (file)
@@ -250,8 +250,10 @@ AS_HELP_STRING([--with-openssl],[use OpenSSL library (default is YES)])
 AS_HELP_STRING([],              [ARG can be prefix for openssl library and headers]),
 GIT_PARSE_WITH([openssl]))
 
-# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
-# able to use Perl-compatible regular expressions.
+# 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.
 #
 # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
 # /foo/bar/include and /foo/bar/lib directories.
@@ -499,8 +501,10 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
 GIT_CONF_SUBST([NO_OPENSSL])
 
 #
-# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
-# able to use Perl-compatible regular expressions.
+# 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.
 #
 
 if test -n "$USE_LIBPCRE"; then
diff --git a/grep.c b/grep.c
index 47cee4506703f5dd2b7db84e09dae93adf99fbaf..d03d424e5cf8d32d91e3082555d8add674e01486 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -178,26 +178,23 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
 
        case GREP_PATTERN_TYPE_BRE:
                opt->fixed = 0;
-               opt->pcre = 0;
-               opt->regflags &= ~REG_EXTENDED;
+               opt->pcre1 = 0;
                break;
 
        case GREP_PATTERN_TYPE_ERE:
                opt->fixed = 0;
-               opt->pcre = 0;
+               opt->pcre1 = 0;
                opt->regflags |= REG_EXTENDED;
                break;
 
        case GREP_PATTERN_TYPE_FIXED:
                opt->fixed = 1;
-               opt->pcre = 0;
-               opt->regflags &= ~REG_EXTENDED;
+               opt->pcre1 = 0;
                break;
 
        case GREP_PATTERN_TYPE_PCRE:
                opt->fixed = 0;
-               opt->pcre = 1;
-               opt->regflags &= ~REG_EXTENDED;
+               opt->pcre1 = 1;
                break;
        }
 }
@@ -324,8 +321,32 @@ static NORETURN void compile_regexp_failed(const struct grep_pat *p,
        die("%s'%s': %s", where, p->pattern, error);
 }
 
-#ifdef USE_LIBPCRE
-static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
+static int is_fixed(const char *s, size_t len)
+{
+       size_t i;
+
+       for (i = 0; i < len; i++) {
+               if (is_regex_special(s[i]))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int has_null(const char *s, size_t len)
+{
+       /*
+        * regcomp cannot accept patterns with NULs so when using it
+        * we consider any pattern containing a NUL fixed.
+        */
+       if (memchr(s, 0, len))
+               return 1;
+
+       return 0;
+}
+
+#ifdef USE_LIBPCRE1
+static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
 {
        const char *error;
        int erroffset;
@@ -333,23 +354,23 @@ static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
 
        if (opt->ignore_case) {
                if (has_non_ascii(p->pattern))
-                       p->pcre_tables = pcre_maketables();
+                       p->pcre1_tables = pcre_maketables();
                options |= PCRE_CASELESS;
        }
        if (is_utf8_locale() && has_non_ascii(p->pattern))
                options |= PCRE_UTF8;
 
-       p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
-                                     p->pcre_tables);
-       if (!p->pcre_regexp)
+       p->pcre1_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
+                                     p->pcre1_tables);
+       if (!p->pcre1_regexp)
                compile_regexp_failed(p, error);
 
-       p->pcre_extra_info = pcre_study(p->pcre_regexp, 0, &error);
-       if (!p->pcre_extra_info && error)
+       p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
+       if (!p->pcre1_extra_info && error)
                die("%s", error);
 }
 
-static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
+static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
                regmatch_t *match, int eflags)
 {
        int ovector[30], ret, flags = 0;
@@ -357,7 +378,7 @@ static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
        if (eflags & REG_NOTBOL)
                flags |= PCRE_NOTBOL;
 
-       ret = pcre_exec(p->pcre_regexp, p->pcre_extra_info, line, eol - line,
+       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);
@@ -370,55 +391,36 @@ static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
        return ret;
 }
 
-static void free_pcre_regexp(struct grep_pat *p)
+static void free_pcre1_regexp(struct grep_pat *p)
 {
-       pcre_free(p->pcre_regexp);
-       pcre_free(p->pcre_extra_info);
-       pcre_free((void *)p->pcre_tables);
+       pcre_free(p->pcre1_regexp);
+       pcre_free(p->pcre1_extra_info);
+       pcre_free((void *)p->pcre1_tables);
 }
-#else /* !USE_LIBPCRE */
-static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
+#else /* !USE_LIBPCRE1 */
+static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
 {
        die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
 }
 
-static int pcrematch(struct grep_pat *p, const char *line, const char *eol,
+static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
                regmatch_t *match, int eflags)
 {
        return 1;
 }
 
-static void free_pcre_regexp(struct grep_pat *p)
+static void free_pcre1_regexp(struct grep_pat *p)
 {
 }
-#endif /* !USE_LIBPCRE */
-
-static int is_fixed(const char *s, size_t len)
-{
-       size_t i;
-
-       /* regcomp cannot accept patterns with NULs so we
-        * consider any pattern containing a NUL fixed.
-        */
-       if (memchr(s, 0, len))
-               return 1;
-
-       for (i = 0; i < len; i++) {
-               if (is_regex_special(s[i]))
-                       return 0;
-       }
-
-       return 1;
-}
+#endif /* !USE_LIBPCRE1 */
 
 static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
 {
        struct strbuf sb = STRBUF_INIT;
        int err;
-       int regflags;
+       int regflags = opt->regflags;
 
        basic_regex_quote_buf(&sb, p->pattern);
-       regflags = opt->regflags & ~REG_EXTENDED;
        if (opt->ignore_case)
                regflags |= REG_ICASE;
        err = regcomp(&p->regexp, sb.buf, regflags);
@@ -455,7 +457,9 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
         * simple string match using kws.  p->fixed tells us if we
         * want to use kws.
         */
-       if (opt->fixed || is_fixed(p->pattern, p->patternlen))
+       if (opt->fixed ||
+           has_null(p->pattern, p->patternlen) ||
+           is_fixed(p->pattern, p->patternlen))
                p->fixed = !icase || ascii_only;
        else
                p->fixed = 0;
@@ -475,8 +479,8 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
                return;
        }
 
-       if (opt->pcre) {
-               compile_pcre_regexp(p, opt);
+       if (opt->pcre1) {
+               compile_pcre1_regexp(p, opt);
                return;
        }
 
@@ -832,8 +836,8 @@ void free_grep_patterns(struct grep_opt *opt)
                case GREP_PATTERN_BODY:
                        if (p->kws)
                                kwsfree(p->kws);
-                       else if (p->pcre_regexp)
-                               free_pcre_regexp(p);
+                       else if (p->pcre1_regexp)
+                               free_pcre1_regexp(p);
                        else
                                regfree(&p->regexp);
                        free(p->pattern);
@@ -912,8 +916,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
 
        if (p->fixed)
                hit = !fixmatch(p, line, eol, match);
-       else if (p->pcre_regexp)
-               hit = !pcrematch(p, line, eol, match, eflags);
+       else if (p->pcre1_regexp)
+               hit = !pcre1match(p, line, eol, match, eflags);
        else
                hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
                                   eflags);
diff --git a/grep.h b/grep.h
index 267534ca24df532505854e1af31c53ed01bab24e..38ac82b6384f8c6a505a8ed764610aa8404f8597 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -1,7 +1,7 @@
 #ifndef GREP_H
 #define GREP_H
 #include "color.h"
-#ifdef USE_LIBPCRE
+#ifdef USE_LIBPCRE1
 #include <pcre.h>
 #else
 typedef int pcre;
@@ -46,9 +46,9 @@ struct grep_pat {
        size_t patternlen;
        enum grep_header_field field;
        regex_t regexp;
-       pcre *pcre_regexp;
-       pcre_extra *pcre_extra_info;
-       const unsigned char *pcre_tables;
+       pcre *pcre1_regexp;
+       pcre_extra *pcre1_extra_info;
+       const unsigned char *pcre1_tables;
        kwset_t kws;
        unsigned fixed:1;
        unsigned ignore_case:1;
@@ -111,7 +111,7 @@ struct grep_opt {
        int allow_textconv;
        int extended;
        int use_reflog_filter;
-       int pcre;
+       int pcre1;
        int relative;
        int pathname;
        int null_following_name;
index 8a8c1789c7bc275db852b6e89a1d3acef3417371..4883cdd2d018b1dc3767ec30a14eac7d6ff84353 100644 (file)
@@ -1991,6 +1991,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
                revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE;
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
+               revs->grep_filter.ignore_case = 1;
                revs->grep_filter.regflags |= REG_ICASE;
                DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
index ab386c36818890a085d8917102b8f8a479ff34cd..2f958603697515f40520a7ff9df31de13eefc2d7 100644 (file)
--- a/t/README
+++ b/t/README
@@ -803,9 +803,9 @@ use these, and "test_set_prereq" for how to define your own.
    Test is not run by root user, and an attempt to write to an
    unwritable file is expected to fail correctly.
 
- - LIBPCRE
+ - PCRE
 
-   Git was compiled with USE_LIBPCRE=YesPlease. Wrap any tests
+   Git was compiled with support for PCRE. Wrap any tests
    that use git-grep --perl-regexp or git-grep -P in these.
 
  - CASE_INSENSITIVE_FS
@@ -817,6 +817,10 @@ use these, and "test_set_prereq" for how to define your own.
    Test is run on a filesystem which converts decomposed utf-8 (nfd)
    to precomposed utf-8 (nfc).
 
+ - PTHREADS
+
+   Git wasn't compiled with NO_PTHREADS=YesPlease.
+
 Tips for Writing Tests
 ----------------------
 
index 49ea4349bedfc53b5b565cf1102c74ccb93ab653..0b6a8d29061066c92f438aad0df958ba4d194717 100644 (file)
@@ -60,7 +60,22 @@ You can set the following variables (also in your config.mak):
 
     GIT_PERF_MAKE_OPTS
        Options to use when automatically building a git tree for
-       performance testing.  E.g., -j6 would be useful.
+       performance testing. E.g., -j6 would be useful. Passed
+       directly to make as "make $GIT_PERF_MAKE_OPTS".
+
+    GIT_PERF_MAKE_COMMAND
+       An arbitrary command that'll be run in place of the make
+       command, if set the GIT_PERF_MAKE_OPTS variable is
+       ignored. Useful in cases where source tree changes might
+       require issuing a different make command to different
+       revisions.
+
+       This can be (ab)used to monkeypatch or otherwise change the
+       tree about to be built. Note that the build directory can be
+       re-used for subsequent runs so the make command might get
+       executed multiple times on the same tree, but don't count on
+       any of that, that's an implementation detail that might change
+       in the future.
 
     GIT_PERF_REPO
     GIT_PERF_LARGE_REPO
diff --git a/t/perf/p4220-log-grep-engines.sh b/t/perf/p4220-log-grep-engines.sh
new file mode 100755 (executable)
index 0000000..2bc47de
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description="Comparison of git-log's --grep regex engines
+
+Set GIT_PERF_4220_LOG_OPTS in the environment to pass options to
+git-grep. Make sure to include a leading space,
+e.g. GIT_PERF_4220_LOG_OPTS=' -i'. Some options to try:
+
+       -i
+       --invert-grep
+       -i --invert-grep
+"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+for pattern in \
+       'how.to' \
+       '^how to' \
+       '[how] to' \
+       '\(e.t[^ ]*\|v.ry\) rare' \
+       'm\(ú\|u\)lt.b\(æ\|y\)te'
+do
+       for engine in basic extended perl
+       do
+               if test $engine != "basic"
+               then
+                       # Poor man's basic -> extended converter.
+                       pattern=$(echo $pattern | sed 's/\\//g')
+               fi
+               if test $engine = "perl" && ! test_have_prereq PCRE
+               then
+                       prereq="PCRE"
+               else
+                       prereq=""
+               fi
+               test_perf $prereq "$engine log$GIT_PERF_4220_LOG_OPTS --grep='$pattern'" "
+                       git -c grep.patternType=$engine log --pretty=format:%h$GIT_PERF_4220_LOG_OPTS --grep='$pattern' >'out.$engine' || :
+               "
+       done
+
+       test_expect_success "assert that all engines found the same for$GIT_PERF_4220_LOG_OPTS '$pattern'" '
+               test_cmp out.basic out.extended &&
+               if test_have_prereq PCRE
+               then
+                       test_cmp out.basic out.perl
+               fi
+       '
+done
+
+test_done
diff --git a/t/perf/p4221-log-grep-engines-fixed.sh b/t/perf/p4221-log-grep-engines-fixed.sh
new file mode 100755 (executable)
index 0000000..0609712
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description="Comparison of git-log's --grep regex engines with -F
+
+Set GIT_PERF_4221_LOG_OPTS in the environment to pass options to
+git-grep. Make sure to include a leading space,
+e.g. GIT_PERF_4221_LOG_OPTS=' -i'. Some options to try:
+
+       -i
+       --invert-grep
+       -i --invert-grep
+"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+for pattern in 'int' 'uncommon' 'æ'
+do
+       for engine in fixed basic extended perl
+       do
+               if test $engine = "perl" && ! test_have_prereq PCRE
+               then
+                       prereq="PCRE"
+               else
+                       prereq=""
+               fi
+               test_perf $prereq "$engine log$GIT_PERF_4221_LOG_OPTS --grep='$pattern'" "
+                       git -c grep.patternType=$engine log --pretty=format:%h$GIT_PERF_4221_LOG_OPTS --grep='$pattern' >'out.$engine' || :
+               "
+       done
+
+       test_expect_success "assert that all engines found the same for$GIT_PERF_4221_LOG_OPTS '$pattern'" '
+               test_cmp out.fixed out.basic &&
+               test_cmp out.fixed out.extended &&
+               if test_have_prereq PCRE
+               then
+                       test_cmp out.fixed out.perl
+               fi
+       '
+done
+
+test_done
diff --git a/t/perf/p7820-grep-engines.sh b/t/perf/p7820-grep-engines.sh
new file mode 100755 (executable)
index 0000000..62aba19
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description="Comparison of git-grep's regex engines
+
+Set GIT_PERF_7820_GREP_OPTS in the environment to pass options to
+git-grep. Make sure to include a leading space,
+e.g. GIT_PERF_7820_GREP_OPTS=' -i'. Some options to try:
+
+       -i
+       -w
+       -v
+       -vi
+       -vw
+       -viw
+"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+for pattern in \
+       'how.to' \
+       '^how to' \
+       '[how] to' \
+       '\(e.t[^ ]*\|v.ry\) rare' \
+       'm\(ú\|u\)lt.b\(æ\|y\)te'
+do
+       for engine in basic extended perl
+       do
+               if test $engine != "basic"
+               then
+                       # Poor man's basic -> extended converter.
+                       pattern=$(echo "$pattern" | sed 's/\\//g')
+               fi
+               if test $engine = "perl" && ! test_have_prereq PCRE
+               then
+                       prereq="PCRE"
+               else
+                       prereq=""
+               fi
+               test_perf $prereq "$engine grep$GIT_PERF_7820_GREP_OPTS '$pattern'" "
+                       git -c grep.patternType=$engine grep$GIT_PERF_7820_GREP_OPTS -- '$pattern' >'out.$engine' || :
+               "
+       done
+
+       test_expect_success "assert that all engines found the same for$GIT_PERF_7820_GREP_OPTS '$pattern'" '
+               test_cmp out.basic out.extended &&
+               if test_have_prereq PCRE
+               then
+                       test_cmp out.basic out.perl
+               fi
+       '
+done
+
+test_done
diff --git a/t/perf/p7821-grep-engines-fixed.sh b/t/perf/p7821-grep-engines-fixed.sh
new file mode 100755 (executable)
index 0000000..c7ef1e1
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description="Comparison of git-grep's regex engines with -F
+
+Set GIT_PERF_7821_GREP_OPTS in the environment to pass options to
+git-grep. Make sure to include a leading space,
+e.g. GIT_PERF_7821_GREP_OPTS=' -w'. See p7820-grep-engines.sh for more
+options to try.
+"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+for pattern in 'int' 'uncommon' 'æ'
+do
+       for engine in fixed basic extended perl
+       do
+               if test $engine = "perl" && ! test_have_prereq PCRE
+               then
+                       prereq="PCRE"
+               else
+                       prereq=""
+               fi
+               test_perf $prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" "
+                       git -c grep.patternType=$engine grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine' || :
+               "
+       done
+
+       test_expect_success "assert that all engines found the same for$GIT_PERF_7821_GREP_OPTS $pattern" '
+               test_cmp out.fixed out.basic &&
+               test_cmp out.fixed out.extended &&
+               if test_have_prereq PCRE
+               then
+                       test_cmp out.fixed out.perl
+               fi
+       '
+done
+
+test_done
index c788d713ae927007866b5b73920de2674f816207..beb4acc0e428d20280a649c428da8b0b3aa5b4c6 100755 (executable)
@@ -24,6 +24,7 @@ run_one_dir () {
 
 unpack_git_rev () {
        rev=$1
+       echo "=== Unpacking $rev in build/$rev ==="
        mkdir -p build/$rev
        (cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) |
        (cd build/$rev && tar x)
@@ -37,8 +38,16 @@ build_git_rev () {
                        cp "../../$config" "build/$rev/"
                fi
        done
-       (cd build/$rev && make $GIT_PERF_MAKE_OPTS) ||
-       die "failed to build revision '$mydir'"
+       echo "=== Building $rev ==="
+       (
+               cd build/$rev &&
+               if test -n "$GIT_PERF_MAKE_COMMAND"
+               then
+                       sh -c "$GIT_PERF_MAKE_COMMAND"
+               else
+                       make $GIT_PERF_MAKE_OPTS
+               fi
+       ) || die "failed to build revision '$mydir'"
 }
 
 run_dirs_helper () {
index 1c7d6729c699dc8c8784d19659551df24530bd05..c44c4337f8fc5c5c1631cbbfe2b5528b88834b87 100755 (executable)
@@ -231,14 +231,47 @@ second
 initial
 EOF
 test_expect_success 'log --invert-grep --grep' '
-       git log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual &&
-       test_cmp expect actual
+       # Fixed
+       git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual &&
+       test_cmp expect actual &&
+
+       # POSIX basic
+       git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
+       test_cmp expect actual &&
+
+       # POSIX extended
+       git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
+       test_cmp expect actual &&
+
+       # PCRE
+       if test_have_prereq PCRE
+       then
+               git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual &&
+               test_cmp expect actual
+       fi
 '
 
 test_expect_success 'log --invert-grep --grep -i' '
        echo initial >expect &&
-       git log --pretty="tformat:%s" --invert-grep -i --grep=th --grep=Sec >actual &&
-       test_cmp expect actual
+
+       # Fixed
+       git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep -i --grep=th --grep=Sec >actual &&
+       test_cmp expect actual &&
+
+       # POSIX basic
+       git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
+       test_cmp expect actual &&
+
+       # POSIX extended
+       git -c grep.patternType=extended log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
+       test_cmp expect actual &&
+
+       # PCRE
+       if test_have_prereq PCRE
+       then
+               git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual &&
+               test_cmp expect actual
+       fi
 '
 
 test_expect_success 'log --grep option parsing' '
@@ -256,13 +289,53 @@ test_expect_success 'log -i --grep' '
 
 test_expect_success 'log --grep -i' '
        echo Second >expect &&
+
+       # Fixed
        git log -1 --pretty="tformat:%s" --grep=sec -i >actual &&
-       test_cmp expect actual
+       test_cmp expect actual &&
+
+       # POSIX basic
+       git -c grep.patternType=basic log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
+       test_cmp expect actual &&
+
+       # POSIX extended
+       git -c grep.patternType=extended log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
+       test_cmp expect actual &&
+
+       # PCRE
+       if test_have_prereq PCRE
+       then
+               git -c grep.patternType=perl log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual &&
+               test_cmp expect actual
+       fi
 '
 
 test_expect_success 'log -F -E --grep=<ere> uses ere' '
        echo second >expect &&
-       git log -1 --pretty="tformat:%s" -F -E --grep=s.c.nd >actual &&
+       # basic would need \(s\) to do the same
+       git log -1 --pretty="tformat:%s" -F -E --grep="(s).c.nd" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success PCRE 'log -F -E --perl-regexp --grep=<pcre> uses PCRE' '
+       test_when_finished "rm -rf num_commits" &&
+       git init num_commits &&
+       (
+               cd num_commits &&
+               test_commit 1d &&
+               test_commit 2e
+       ) &&
+
+       # In PCRE \d in [\d] is like saying "0-9", and matches the 2
+       # in 2e...
+       echo 2e >expect &&
+       git -C num_commits log -1 --pretty="tformat:%s" -F -E --perl-regexp --grep="[\d]" >actual &&
+       test_cmp expect actual &&
+
+       # ...in POSIX basic and extended it is the same as [d],
+       # i.e. "d", which matches 1d, but does not match 2e.
+       echo 1d >expect &&
+       git -C num_commits log -1 --pretty="tformat:%s" -F -E --grep="[\d]" >actual &&
        test_cmp expect actual
 '
 
@@ -280,6 +353,81 @@ test_expect_success 'log with grep.patternType configuration and command line' '
        test_cmp expect actual
 '
 
+test_expect_success 'log with various grep.patternType configurations & command-lines' '
+       git init pattern-type &&
+       (
+               cd pattern-type &&
+               test_commit 1 file A &&
+
+               # The tagname is overridden here because creating a
+               # tag called "(1|2)" as test_commit would otherwise
+               # implicitly do would fail on e.g. MINGW.
+               test_commit "(1|2)" file B 2 &&
+
+               echo "(1|2)" >expect.fixed &&
+               cp expect.fixed expect.basic &&
+               cp expect.fixed expect.extended &&
+               cp expect.fixed expect.perl &&
+
+               # A strcmp-like match with fixed.
+               git -c grep.patternType=fixed log --pretty=tformat:%s \
+                       --grep="(1|2)" >actual.fixed &&
+
+               # POSIX basic matches (, | and ) literally.
+               git -c grep.patternType=basic log --pretty=tformat:%s \
+                       --grep="(.|.)" >actual.basic &&
+
+               # POSIX extended needs to have | escaped to match it
+               # literally, whereas under basic this is the same as
+               # (|2), i.e. it would also match "1". This test checks
+               # for extended by asserting that it is not matching
+               # what basic would match.
+               git -c grep.patternType=extended log --pretty=tformat:%s \
+                       --grep="\|2" >actual.extended &&
+               if test_have_prereq PCRE
+               then
+                       # Only PCRE would match [\d]\| with only
+                       # "(1|2)" due to [\d]. POSIX basic would match
+                       # both it and "1" since similarly to the
+                       # extended match above it is the same as
+                       # \([\d]\|\). POSIX extended would
+                       # match neither.
+                       git -c grep.patternType=perl log --pretty=tformat:%s \
+                               --grep="[\d]\|" >actual.perl &&
+                       test_cmp expect.perl actual.perl
+               fi &&
+               test_cmp expect.fixed actual.fixed &&
+               test_cmp expect.basic actual.basic &&
+               test_cmp expect.extended actual.extended &&
+
+               git log --pretty=tformat:%s -F \
+                       --grep="(1|2)" >actual.fixed.short-arg &&
+               git log --pretty=tformat:%s -E \
+                       --grep="\|2" >actual.extended.short-arg &&
+               test_cmp expect.fixed actual.fixed.short-arg &&
+               test_cmp expect.extended actual.extended.short-arg &&
+
+               git log --pretty=tformat:%s --fixed-strings \
+                       --grep="(1|2)" >actual.fixed.long-arg &&
+               git log --pretty=tformat:%s --basic-regexp \
+                       --grep="(.|.)" >actual.basic.long-arg &&
+               git log --pretty=tformat:%s --extended-regexp \
+                       --grep="\|2" >actual.extended.long-arg &&
+               if test_have_prereq PCRE
+               then
+                       git log --pretty=tformat:%s --perl-regexp \
+                               --grep="[\d]\|" >actual.perl.long-arg &&
+                       test_cmp expect.perl actual.perl.long-arg
+               else
+                       test_must_fail git log --perl-regexp \
+                               --grep="[\d]\|"
+               fi &&
+               test_cmp expect.fixed actual.fixed.long-arg &&
+               test_cmp expect.basic actual.basic.long-arg &&
+               test_cmp expect.extended actual.extended.long-arg
+       )
+'
+
 cat > expect <<EOF
 * Second
 * sixth
index 43a672c3451146f800852a6d8688c10e497b47cf..9c68b992511b7098df0570ca37e0add468a8a093 100755 (executable)
@@ -421,6 +421,42 @@ test_expect_success 'index-pack <pack> works in non-repo' '
        test_path_is_file foo.idx
 '
 
+test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'index-pack --threads=N or pack.threads=N warns when no pthreads' '
+       test_must_fail git index-pack --threads=2 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring --threads=2" err &&
+
+       test_must_fail git -c pack.threads=2 index-pack 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring pack.threads" err &&
+
+       test_must_fail git -c pack.threads=2 index-pack --threads=4 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 2 warnings &&
+       grep -F "no threads support, ignoring --threads=4" err &&
+       grep -F "no threads support, ignoring pack.threads" err
+'
+
+test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'pack-objects --threads=N or pack.threads=N warns when no pthreads' '
+       git pack-objects --threads=2 --stdout --all </dev/null >/dev/null 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring --threads" err &&
+
+       git -c pack.threads=2 pack-objects --stdout --all </dev/null >/dev/null 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring pack.threads" err &&
+
+       git -c pack.threads=2 pack-objects --threads=4 --stdout --all </dev/null >/dev/null 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 2 warnings &&
+       grep -F "no threads support, ignoring --threads" err &&
+       grep -F "no threads support, ignoring pack.threads" err
+'
+
 #
 # WARNING!
 #
index 9c9c378119defa7884a21beb27e806ddf1171497..615e7e0162518087fff355bac156ba8bbdd6df38 100755 (executable)
@@ -4,8 +4,43 @@ test_description='git grep in binary files'
 
 . ./test-lib.sh
 
+nul_match () {
+       matches=$1
+       flags=$2
+       pattern=$3
+       pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g')
+
+       if test "$matches" = 1
+       then
+               test_expect_success "git grep -f f $flags '$pattern_human' a" "
+                       printf '$pattern' | q_to_nul >f &&
+                       git grep -f f $flags a
+               "
+       elif test "$matches" = 0
+       then
+               test_expect_success "git grep -f f $flags '$pattern_human' a" "
+                       printf '$pattern' | q_to_nul >f &&
+                       test_must_fail git grep -f f $flags a
+               "
+       elif test "$matches" = T1
+       then
+               test_expect_failure "git grep -f f $flags '$pattern_human' a" "
+                       printf '$pattern' | q_to_nul >f &&
+                       git grep -f f $flags a
+               "
+       elif test "$matches" = T0
+       then
+               test_expect_failure "git grep -f f $flags '$pattern_human' a" "
+                       printf '$pattern' | q_to_nul >f &&
+                       test_must_fail git grep -f f $flags a
+               "
+       else
+               test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false'
+       fi
+}
+
 test_expect_success 'setup' "
-       echo 'binaryQfile' | q_to_nul >a &&
+       echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a &&
        git add a &&
        git commit -m.
 "
@@ -69,35 +104,71 @@ test_expect_failure 'git grep .fi a' '
        git grep .fi a
 '
 
-test_expect_success 'git grep -F y<NUL>f a' "
-       printf 'yQf' | q_to_nul >f &&
-       git grep -f f -F a
-"
-
-test_expect_success 'git grep -F y<NUL>x a' "
-       printf 'yQx' | q_to_nul >f &&
-       test_must_fail git grep -f f -F a
-"
-
-test_expect_success 'git grep -Fi Y<NUL>f a' "
-       printf 'YQf' | q_to_nul >f &&
-       git grep -f f -Fi a
-"
-
-test_expect_success 'git grep -Fi Y<NUL>x a' "
-       printf 'YQx' | q_to_nul >f &&
-       test_must_fail git grep -f f -Fi a
-"
-
-test_expect_success 'git grep y<NUL>f a' "
-       printf 'yQf' | q_to_nul >f &&
-       git grep -f f a
-"
-
-test_expect_success 'git grep y<NUL>x a' "
-       printf 'yQx' | q_to_nul >f &&
-       test_must_fail git grep -f f a
-"
+nul_match 1 '-F' 'yQf'
+nul_match 0 '-F' 'yQx'
+nul_match 1 '-Fi' 'YQf'
+nul_match 0 '-Fi' 'YQx'
+nul_match 1 '' 'yQf'
+nul_match 0 '' 'yQx'
+nul_match 1 '' 'æQð'
+nul_match 1 '-F' 'eQm[*]c'
+nul_match 1 '-Fi' 'EQM[*]C'
+
+# Regex patterns that would match but shouldn't with -F
+nul_match 0 '-F' 'yQ[f]'
+nul_match 0 '-F' '[y]Qf'
+nul_match 0 '-Fi' 'YQ[F]'
+nul_match 0 '-Fi' '[Y]QF'
+nul_match 0 '-F' 'æQ[ð]'
+nul_match 0 '-F' '[æ]Qð'
+nul_match 0 '-Fi' 'ÆQ[Ð]'
+nul_match 0 '-Fi' '[Æ]QÐ'
+
+# kwset is disabled on -i & non-ASCII. No way to match non-ASCII \0
+# patterns case-insensitively.
+nul_match T1 '-i' 'ÆQÐ'
+
+# \0 implicitly disables regexes. This is an undocumented internal
+# limitation.
+nul_match T1 '' 'yQ[f]'
+nul_match T1 '' '[y]Qf'
+nul_match T1 '-i' 'YQ[F]'
+nul_match T1 '-i' '[Y]Qf'
+nul_match T1 '' 'æQ[ð]'
+nul_match T1 '' '[æ]Qð'
+nul_match T1 '-i' 'ÆQ[Ð]'
+
+# ... because of \0 implicitly disabling regexes regexes that
+# should/shouldn't match don't do the right thing.
+nul_match T1 '' 'eQm.*cQ'
+nul_match T1 '-i' 'EQM.*cQ'
+nul_match T0 '' 'eQm[*]c'
+nul_match T0 '-i' 'EQM[*]C'
+
+# Due to the REG_STARTEND extension when kwset() is disabled on -i &
+# non-ASCII the string will be matched in its entirety, but the
+# pattern will be cut off at the first \0.
+nul_match 0 '-i' 'NOMATCHQð'
+nul_match T0 '-i' '[Æ]QNOMATCH'
+nul_match T0 '-i' '[æ]QNOMATCH'
+# Matches, but for the wrong reasons, just stops at [æ]
+nul_match 1 '-i' '[Æ]Qð'
+nul_match 1 '-i' '[æ]Qð'
+
+# Ensure that the matcher doesn't regress to something that stops at
+# \0
+nul_match 0 '-F' 'yQ[f]'
+nul_match 0 '-Fi' 'YQ[F]'
+nul_match 0 '' 'yQNOMATCH'
+nul_match 0 '' 'QNOMATCH'
+nul_match 0 '-i' 'YQNOMATCH'
+nul_match 0 '-i' 'QNOMATCH'
+nul_match 0 '-F' 'æQ[ð]'
+nul_match 0 '-Fi' 'ÆQ[Ð]'
+nul_match 0 '' 'yQNÓMATCH'
+nul_match 0 '' 'QNÓMATCH'
+nul_match 0 '-i' 'YQNÓMATCH'
+nul_match 0 '-i' 'QNÓMATCH'
 
 test_expect_success 'grep respects binary diff attribute' '
        echo text >t &&
@@ -162,7 +233,7 @@ test_expect_success 'grep does not honor textconv' '
 '
 
 test_expect_success 'grep --textconv honors textconv' '
-       echo "a:binaryQfile" >expect &&
+       echo "a:binaryQfileQm[*]cQ*æQð" >expect &&
        git grep --textconv Qfile >actual &&
        test_cmp expect actual
 '
@@ -172,7 +243,7 @@ test_expect_success 'grep --no-textconv does not honor textconv' '
 '
 
 test_expect_success 'grep --textconv blob honors textconv' '
-       echo "HEAD:a:binaryQfile" >expect &&
+       echo "HEAD:a:binaryQfileQm[*]cQ*æQð" >expect &&
        git grep --textconv Qfile HEAD:a >actual &&
        test_cmp expect actual
 '
index cee42097b077378f42910666a7895347b0787b1a..f1063878205cfb9b0af8e54d997040ddb65bc27e 100755 (executable)
@@ -275,12 +275,16 @@ do
                test_cmp expected actual
        '
 
-       test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" '
+       test_expect_success PCRE "grep $L with grep.patterntype=perl" '
                echo "${HC}ab:a+b*c" >expected &&
                git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual &&
                test_cmp expected actual
        '
 
+       test_expect_success !PCRE "grep $L with grep.patterntype=perl errors without PCRE" '
+               test_must_fail git -c grep.patterntype=perl grep "foo.*bar"
+       '
+
        test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
                echo "${HC}ab:abc" >expected &&
                git \
@@ -771,6 +775,40 @@ test_expect_success 'grep -W with userdiff' '
        test_cmp expected actual
 '
 
+for threads in $(test_seq 0 10)
+do
+       test_expect_success "grep --threads=$threads & -c grep.threads=$threads" "
+               git grep --threads=$threads . >actual.$threads &&
+               if test $threads -ge 1
+               then
+                       test_cmp actual.\$(($threads - 1)) actual.$threads
+               fi &&
+               git -c grep.threads=$threads grep . >actual.$threads &&
+               if test $threads -ge 1
+               then
+                       test_cmp actual.\$(($threads - 1)) actual.$threads
+               fi
+       "
+done
+
+test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'grep --threads=N or pack.threads=N warns when no pthreads' '
+       git grep --threads=2 Hello hello_world 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring --threads" err &&
+       git -c grep.threads=2 grep Hello hello_world 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 1 warnings &&
+       grep -F "no threads support, ignoring grep.threads" err &&
+       git -c grep.threads=2 grep --threads=4 Hello hello_world 2>err &&
+       grep ^warning: err >warnings &&
+       test_line_count = 2 warnings &&
+       grep -F "no threads support, ignoring --threads" err &&
+       grep -F "no threads support, ignoring grep.threads" err &&
+       git -c grep.threads=0 grep --threads=0 Hello hello_world 2>err &&
+       test_line_count = 0 err
+'
+
 test_expect_success 'grep from a subdirectory to search wider area (1)' '
        mkdir -p s &&
        (
@@ -1053,16 +1091,24 @@ hello.c:int main(int argc, const char **argv)
 hello.c:       printf("Hello world.\n");
 EOF
 
-test_expect_success LIBPCRE 'grep --perl-regexp pattern' '
+test_expect_success PCRE 'grep --perl-regexp pattern' '
        git grep --perl-regexp "\p{Ps}.*?\p{Pe}" hello.c >actual &&
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P pattern' '
+test_expect_success !PCRE 'grep --perl-regexp pattern errors without PCRE' '
+       test_must_fail git grep --perl-regexp "foo.*bar"
+'
+
+test_expect_success PCRE 'grep -P pattern' '
        git grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
        test_cmp expected actual
 '
 
+test_expect_success !PCRE 'grep -P pattern errors without PCRE' '
+       test_must_fail git grep -P "foo.*bar"
+'
+
 test_expect_success 'grep pattern with grep.extendedRegexp=true' '
        >empty &&
        test_must_fail git -c grep.extendedregexp=true \
@@ -1070,13 +1116,13 @@ test_expect_success 'grep pattern with grep.extendedRegexp=true' '
        test_cmp empty actual
 '
 
-test_expect_success LIBPCRE 'grep -P pattern with grep.extendedRegexp=true' '
+test_expect_success PCRE 'grep -P pattern with grep.extendedRegexp=true' '
        git -c grep.extendedregexp=true \
                grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P -v pattern' '
+test_expect_success PCRE 'grep -P -v pattern' '
        {
                echo "ab:a+b*c"
                echo "ab:a+bc"
@@ -1085,7 +1131,7 @@ test_expect_success LIBPCRE 'grep -P -v pattern' '
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P -i pattern' '
+test_expect_success PCRE 'grep -P -i pattern' '
        cat >expected <<-EOF &&
        hello.c:        printf("Hello world.\n");
        EOF
@@ -1093,7 +1139,7 @@ test_expect_success LIBPCRE 'grep -P -i pattern' '
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P -w pattern' '
+test_expect_success PCRE 'grep -P -w pattern' '
        {
                echo "hello_world:Hello world"
                echo "hello_world:HeLLo world"
@@ -1102,6 +1148,13 @@ test_expect_success LIBPCRE 'grep -P -w pattern' '
        test_cmp expected actual
 '
 
+test_expect_success PCRE 'grep -P backreferences work (the PCRE NO_AUTO_CAPTURE flag is not set)' '
+       git grep -P -h "(?P<one>.)(?P=one)" hello_world >actual &&
+       test_cmp hello_world actual &&
+       git grep -P -h "(.)\1" hello_world >actual &&
+       test_cmp hello_world actual
+'
+
 test_expect_success 'grep -G invalidpattern properly dies ' '
        test_must_fail git grep -G "a["
 '
@@ -1118,11 +1171,11 @@ test_expect_success 'grep invalidpattern properly dies with grep.patternType=ext
        test_must_fail git -c grep.patterntype=extended grep "a["
 '
 
-test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' '
+test_expect_success PCRE 'grep -P invalidpattern properly dies ' '
        test_must_fail git grep -P "a["
 '
 
-test_expect_success LIBPCRE 'grep invalidpattern properly dies with grep.patternType=perl' '
+test_expect_success PCRE 'grep invalidpattern properly dies with grep.patternType=perl' '
        test_must_fail git -c grep.patterntype=perl grep "a["
 '
 
@@ -1191,13 +1244,13 @@ test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =e
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
+test_expect_success PCRE 'grep -G -F -E -P pattern' '
        echo "d0:0" >expected &&
        git grep -G -F -E -P "[\d]" d0 >actual &&
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '
+test_expect_success PCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '
        echo "d0:0" >expected &&
        git \
                -c grep.patterntype=fixed \
@@ -1208,7 +1261,7 @@ test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P pattern with grep.patternType=fixed' '
+test_expect_success PCRE 'grep -P pattern with grep.patternType=fixed' '
        echo "ab:a+b*c" >expected &&
        git \
                -c grep.patterntype=fixed \
@@ -1343,12 +1396,12 @@ space: line with leading space2
 space: line with leading space3
 EOF
 
-test_expect_success LIBPCRE 'grep -E "^ "' '
+test_expect_success PCRE 'grep -E "^ "' '
        git grep -E "^ " space >actual &&
        test_cmp expected actual
 '
 
-test_expect_success LIBPCRE 'grep -P "^ "' '
+test_expect_success PCRE 'grep -P "^ "' '
        git grep -P "^ " space >actual &&
        test_cmp expected actual
 '
index 169fd8d7065f89ce78f5241eeb7bf376c3f3172d..0059a1f837882c504e717135c9c92bc5b1d7f62c 100755 (executable)
@@ -20,13 +20,13 @@ test_expect_success REGEX_LOCALE 'grep literal string, no -F' '
        git grep -i "TILRAUN: HALLÓ HEIMUR!"
 '
 
-test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 icase' '
+test_expect_success GETTEXT_LOCALE,PCRE 'grep pcre utf-8 icase' '
        git grep --perl-regexp    "TILRAUN: H.lló Heimur!" &&
        git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" &&
        git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!"
 '
 
-test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' '
+test_expect_success GETTEXT_LOCALE,PCRE 'grep pcre utf-8 string with "+"' '
        test_write_lines "TILRAUN: Hallóó Heimur!" >file2 &&
        git add file2 &&
        git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual &&
@@ -36,29 +36,14 @@ test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' '
 '
 
 test_expect_success REGEX_LOCALE 'grep literal string, with -F' '
-       git grep --debug -i -F "TILRAUN: Halló Heimur!"  2>&1 >/dev/null |
-                grep fixed >debug1 &&
-       test_write_lines "fixed TILRAUN: Halló Heimur!" >expect1 &&
-       test_cmp expect1 debug1 &&
-
-       git grep --debug -i -F "TILRAUN: HALLÓ HEIMUR!"  2>&1 >/dev/null |
-                grep fixed >debug2 &&
-       test_write_lines "fixed TILRAUN: HALLÓ HEIMUR!" >expect2 &&
-       test_cmp expect2 debug2
+       git grep -i -F "TILRAUN: Halló Heimur!" &&
+       git grep -i -F "TILRAUN: HALLÓ HEIMUR!"
 '
 
 test_expect_success REGEX_LOCALE 'grep string with regex, with -F' '
-       test_write_lines "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file &&
-
-       git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 >/dev/null |
-                grep fixed >debug1 &&
-       test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\Halló \$He\\[]imur!\\\$" >expect1 &&
-       test_cmp expect1 debug1 &&
-
-       git grep --debug -i -F "^*TILR^AUN:.* \\HALLÓ \$HE[]IMUR!\$"  2>&1 >/dev/null |
-                grep fixed >debug2 &&
-       test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\HALLÓ \$HE\\[]IMUR!\\\$" >expect2 &&
-       test_cmp expect2 debug2
+       test_write_lines "TILRAUN: Halló Heimur [abc]!" >file3 &&
+       git add file3 &&
+       git grep -i -F "TILRAUN: Halló Heimur [abc]!" file3
 '
 
 test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' '
index efef7fb81fa4f8ed56d12c6519cb4ee7500ba3da..701e08a8e5941d711ffbef52da972acb7ab9a41e 100755 (executable)
@@ -11,7 +11,7 @@ test_expect_success GETTEXT_ISO_LOCALE 'setup' '
        export LC_ALL
 '
 
-test_expect_success GETTEXT_ISO_LOCALE,LIBPCRE 'grep pcre string' '
+test_expect_success GETTEXT_ISO_LOCALE,PCRE 'grep pcre string' '
        git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" &&
        git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!"
 '
index 5b6eb3a65e26263db526c2e891ae01a4578bf48e..3a58197f472f38c320de33fa82896c0a77d125ae 100755 (executable)
@@ -9,13 +9,13 @@ submodules.
 . ./test-lib.sh
 
 test_expect_success 'setup directory structure and submodule' '
-       echo "foobar" >a &&
+       echo "(1|2)d(3|4)" >a &&
        mkdir b &&
-       echo "bar" >b/b &&
+       echo "(3|4)" >b/b &&
        git add a b &&
        git commit -m "add a and b" &&
        git init submodule &&
-       echo "foobar" >submodule/a &&
+       echo "(1|2)d(3|4)" >submodule/a &&
        git -C submodule add a &&
        git -C submodule commit -m "add a" &&
        git submodule add ./submodule &&
@@ -24,18 +24,18 @@ test_expect_success 'setup directory structure and submodule' '
 
 test_expect_success 'grep correctly finds patterns in a submodule' '
        cat >expect <<-\EOF &&
-       a:foobar
-       b/b:bar
-       submodule/a:foobar
+       a:(1|2)d(3|4)
+       b/b:(3|4)
+       submodule/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules >actual &&
+       git grep -e "(3|4)" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep and basic pathspecs' '
        cat >expect <<-\EOF &&
-       submodule/a:foobar
+       submodule/a:(1|2)d(3|4)
        EOF
 
        git grep -e. --recurse-submodules -- submodule >actual &&
@@ -44,7 +44,7 @@ test_expect_success 'grep and basic pathspecs' '
 
 test_expect_success 'grep and nested submodules' '
        git init submodule/sub &&
-       echo "foobar" >submodule/sub/a &&
+       echo "(1|2)d(3|4)" >submodule/sub/a &&
        git -C submodule/sub add a &&
        git -C submodule/sub commit -m "add a" &&
        git -C submodule submodule add ./sub &&
@@ -54,117 +54,117 @@ test_expect_success 'grep and nested submodules' '
        git commit -m "updated submodule" &&
 
        cat >expect <<-\EOF &&
-       a:foobar
-       b/b:bar
-       submodule/a:foobar
-       submodule/sub/a:foobar
+       a:(1|2)d(3|4)
+       b/b:(3|4)
+       submodule/a:(1|2)d(3|4)
+       submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules >actual &&
+       git grep -e "(3|4)" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep and multiple patterns' '
        cat >expect <<-\EOF &&
-       a:foobar
-       submodule/a:foobar
-       submodule/sub/a:foobar
+       a:(1|2)d(3|4)
+       submodule/a:(1|2)d(3|4)
+       submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --and -e "foo" --recurse-submodules >actual &&
+       git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep and multiple patterns' '
        cat >expect <<-\EOF &&
-       b/b:bar
+       b/b:(3|4)
        EOF
 
-       git grep -e "bar" --and --not -e "foo" --recurse-submodules >actual &&
+       git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'basic grep tree' '
        cat >expect <<-\EOF &&
-       HEAD:a:foobar
-       HEAD:b/b:bar
-       HEAD:submodule/a:foobar
-       HEAD:submodule/sub/a:foobar
+       HEAD:a:(1|2)d(3|4)
+       HEAD:b/b:(3|4)
+       HEAD:submodule/a:(1|2)d(3|4)
+       HEAD:submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree HEAD^' '
        cat >expect <<-\EOF &&
-       HEAD^:a:foobar
-       HEAD^:b/b:bar
-       HEAD^:submodule/a:foobar
+       HEAD^:a:(1|2)d(3|4)
+       HEAD^:b/b:(3|4)
+       HEAD^:submodule/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD^ >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree HEAD^^' '
        cat >expect <<-\EOF &&
-       HEAD^^:a:foobar
-       HEAD^^:b/b:bar
+       HEAD^^:a:(1|2)d(3|4)
+       HEAD^^:b/b:(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD^^ >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree and pathspecs' '
        cat >expect <<-\EOF &&
-       HEAD:submodule/a:foobar
-       HEAD:submodule/sub/a:foobar
+       HEAD:submodule/a:(1|2)d(3|4)
+       HEAD:submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD -- submodule >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree and pathspecs' '
        cat >expect <<-\EOF &&
-       HEAD:submodule/a:foobar
-       HEAD:submodule/sub/a:foobar
+       HEAD:submodule/a:(1|2)d(3|4)
+       HEAD:submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD -- "submodule*a" >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree and more pathspecs' '
        cat >expect <<-\EOF &&
-       HEAD:submodule/a:foobar
+       HEAD:submodule/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD -- "submodul?/a" >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep tree and more pathspecs' '
        cat >expect <<-\EOF &&
-       HEAD:submodule/sub/a:foobar
+       HEAD:submodule/sub/a:(1|2)d(3|4)
        EOF
 
-       git grep -e "bar" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
+       git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual &&
        test_cmp expect actual
 '
 
 test_expect_success !MINGW 'grep recurse submodule colon in name' '
        git init parent &&
        test_when_finished "rm -rf parent" &&
-       echo "foobar" >"parent/fi:le" &&
+       echo "(1|2)d(3|4)" >"parent/fi:le" &&
        git -C parent add "fi:le" &&
        git -C parent commit -m "add fi:le" &&
 
        git init "su:b" &&
        test_when_finished "rm -rf su:b" &&
-       echo "foobar" >"su:b/fi:le" &&
+       echo "(1|2)d(3|4)" >"su:b/fi:le" &&
        git -C "su:b" add "fi:le" &&
        git -C "su:b" commit -m "add fi:le" &&
 
@@ -172,30 +172,30 @@ test_expect_success !MINGW 'grep recurse submodule colon in name' '
        git -C parent commit -m "add submodule" &&
 
        cat >expect <<-\EOF &&
-       fi:le:foobar
-       su:b/fi:le:foobar
+       fi:le:(1|2)d(3|4)
+       su:b/fi:le:(1|2)d(3|4)
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules >actual &&
+       git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
        test_cmp expect actual &&
 
        cat >expect <<-\EOF &&
-       HEAD:fi:le:foobar
-       HEAD:su:b/fi:le:foobar
+       HEAD:fi:le:(1|2)d(3|4)
+       HEAD:su:b/fi:le:(1|2)d(3|4)
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules HEAD >actual &&
+       git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep history with moved submoules' '
        git init parent &&
        test_when_finished "rm -rf parent" &&
-       echo "foobar" >parent/file &&
+       echo "(1|2)d(3|4)" >parent/file &&
        git -C parent add file &&
        git -C parent commit -m "add file" &&
 
        git init sub &&
        test_when_finished "rm -rf sub" &&
-       echo "foobar" >sub/file &&
+       echo "(1|2)d(3|4)" >sub/file &&
        git -C sub add file &&
        git -C sub commit -m "add file" &&
 
@@ -203,82 +203,82 @@ test_expect_success 'grep history with moved submoules' '
        git -C parent commit -m "add submodule" &&
 
        cat >expect <<-\EOF &&
-       dir/sub/file:foobar
-       file:foobar
+       dir/sub/file:(1|2)d(3|4)
+       file:(1|2)d(3|4)
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules >actual &&
+       git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
        test_cmp expect actual &&
 
        git -C parent mv dir/sub sub-moved &&
        git -C parent commit -m "moved submodule" &&
 
        cat >expect <<-\EOF &&
-       file:foobar
-       sub-moved/file:foobar
+       file:(1|2)d(3|4)
+       sub-moved/file:(1|2)d(3|4)
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules >actual &&
+       git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual &&
        test_cmp expect actual &&
 
        cat >expect <<-\EOF &&
-       HEAD^:dir/sub/file:foobar
-       HEAD^:file:foobar
+       HEAD^:dir/sub/file:(1|2)d(3|4)
+       HEAD^:file:(1|2)d(3|4)
        EOF
-       git -C parent grep -e "foobar" --recurse-submodules HEAD^ >actual &&
+       git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep using relative path' '
        test_when_finished "rm -rf parent sub" &&
        git init sub &&
-       echo "foobar" >sub/file &&
+       echo "(1|2)d(3|4)" >sub/file &&
        git -C sub add file &&
        git -C sub commit -m "add file" &&
 
        git init parent &&
-       echo "foobar" >parent/file &&
+       echo "(1|2)d(3|4)" >parent/file &&
        git -C parent add file &&
        mkdir parent/src &&
-       echo "foobar" >parent/src/file2 &&
+       echo "(1|2)d(3|4)" >parent/src/file2 &&
        git -C parent add src/file2 &&
        git -C parent submodule add ../sub &&
        git -C parent commit -m "add files and submodule" &&
 
        # From top works
        cat >expect <<-\EOF &&
-       file:foobar
-       src/file2:foobar
-       sub/file:foobar
+       file:(1|2)d(3|4)
+       src/file2:(1|2)d(3|4)
+       sub/file:(1|2)d(3|4)
        EOF
-       git -C parent grep --recurse-submodules -e "foobar" >actual &&
+       git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
        test_cmp expect actual &&
 
        # Relative path to top
        cat >expect <<-\EOF &&
-       ../file:foobar
-       file2:foobar
-       ../sub/file:foobar
+       ../file:(1|2)d(3|4)
+       file2:(1|2)d(3|4)
+       ../sub/file:(1|2)d(3|4)
        EOF
-       git -C parent/src grep --recurse-submodules -e "foobar" -- .. >actual &&
+       git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual &&
        test_cmp expect actual &&
 
        # Relative path to submodule
        cat >expect <<-\EOF &&
-       ../sub/file:foobar
+       ../sub/file:(1|2)d(3|4)
        EOF
-       git -C parent/src grep --recurse-submodules -e "foobar" -- ../sub >actual &&
+       git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'grep from a subdir' '
        test_when_finished "rm -rf parent sub" &&
        git init sub &&
-       echo "foobar" >sub/file &&
+       echo "(1|2)d(3|4)" >sub/file &&
        git -C sub add file &&
        git -C sub commit -m "add file" &&
 
        git init parent &&
        mkdir parent/src &&
-       echo "foobar" >parent/src/file &&
+       echo "(1|2)d(3|4)" >parent/src/file &&
        git -C parent add src/file &&
        git -C parent submodule add ../sub src/sub &&
        git -C parent submodule add ../sub sub &&
@@ -286,19 +286,19 @@ test_expect_success 'grep from a subdir' '
 
        # Verify grep from root works
        cat >expect <<-\EOF &&
-       src/file:foobar
-       src/sub/file:foobar
-       sub/file:foobar
+       src/file:(1|2)d(3|4)
+       src/sub/file:(1|2)d(3|4)
+       sub/file:(1|2)d(3|4)
        EOF
-       git -C parent grep --recurse-submodules -e "foobar" >actual &&
+       git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
        test_cmp expect actual &&
 
        # Verify grep from a subdir works
        cat >expect <<-\EOF &&
-       file:foobar
-       sub/file:foobar
+       file:(1|2)d(3|4)
+       sub/file:(1|2)d(3|4)
        EOF
-       git -C parent/src grep --recurse-submodules -e "foobar" >actual &&
+       git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual &&
        test_cmp expect actual
 '
 
@@ -313,4 +313,53 @@ test_incompatible_with_recurse_submodules ()
 test_incompatible_with_recurse_submodules --untracked
 test_incompatible_with_recurse_submodules --no-index
 
+test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
+       # Fixed
+       test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" &&
+       test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" &&
+
+       # Basic
+       git grep -G --recurse-submodules -e "(.|.)[\d]" >actual &&
+       cat >expect <<-\EOF &&
+       a:(1|2)d(3|4)
+       submodule/a:(1|2)d(3|4)
+       submodule/sub/a:(1|2)d(3|4)
+       EOF
+       test_cmp expect actual &&
+       git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual &&
+       test_cmp expect actual &&
+
+       # Extended
+       git grep -E --recurse-submodules -e "(.|.)[\d]" >actual &&
+       cat >expect <<-\EOF &&
+       .gitmodules:[submodule "submodule"]
+       .gitmodules:    path = submodule
+       .gitmodules:    url = ./submodule
+       a:(1|2)d(3|4)
+       submodule/.gitmodules:[submodule "sub"]
+       submodule/a:(1|2)d(3|4)
+       submodule/sub/a:(1|2)d(3|4)
+       EOF
+       test_cmp expect actual &&
+       git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual &&
+       test_cmp expect actual &&
+       git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual &&
+       test_cmp expect actual &&
+
+       # Perl
+       if test_have_prereq PCRE
+       then
+               git grep -P --recurse-submodules -e "(.|.)[\d]" >actual &&
+               cat >expect <<-\EOF &&
+               a:(1|2)d(3|4)
+               b/b:(3|4)
+               submodule/a:(1|2)d(3|4)
+               submodule/sub/a:(1|2)d(3|4)
+               EOF
+               test_cmp expect actual &&
+               git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual &&
+               test_cmp expect actual
+       fi
+'
+
 test_done
index 26b3edfb2e4e725f589fc99986587aa3ecb48b75..43529451f9ae6c7ec63a475b008722751e7c9c29 100644 (file)
@@ -1013,8 +1013,9 @@ esac
 
 ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1
 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_LIBPCRE" && test_set_prereq LIBPCRE
+test -n "$USE_LIBPCRE1" && test_set_prereq PCRE
 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
 
 # Can we rely on git's output in the C locale?