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
  ...
This commit is contained in:
Junio C Hamano 2017-06-02 15:06:05 +09:00
commit 36dcb57337
24 changed files with 838 additions and 234 deletions

View file

@ -161,8 +161,11 @@ OPTIONS
-P:: -P::
--perl-regexp:: --perl-regexp::
Use Perl-compatible regexp for patterns. Requires libpcre to be Use Perl-compatible regular expressions for patterns.
compiled in. +
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:: -F::
--fixed-strings:: --fixed-strings::

View file

@ -92,8 +92,12 @@ endif::git-rev-list[]
pattern as a regular expression). pattern as a regular expression).
--perl-regexp:: --perl-regexp::
Consider the limiting patterns to be Perl-compatible regular expressions. Consider the limiting patterns to be Perl-compatible regular
Requires libpcre to be compiled in. 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:: --remove-empty::
Stop when a given path disappears from the tree. Stop when a given path disappears from the tree.

View file

@ -24,8 +24,10 @@ all::
# Define NO_OPENSSL environment variable if you do not have OpenSSL. # Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies BLK_SHA1. # This also implies BLK_SHA1.
# #
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be # Define USE_LIBPCRE if you have and want to use libpcre. Various
# able to use Perl-compatible regular expressions. # 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 # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
# /foo/bar/include and /foo/bar/lib directories. # /foo/bar/include and /foo/bar/lib directories.
@ -1087,7 +1089,7 @@ ifdef NO_LIBGEN_H
endif endif
ifdef USE_LIBPCRE ifdef USE_LIBPCRE
BASIC_CFLAGS += -DUSE_LIBPCRE BASIC_CFLAGS += -DUSE_LIBPCRE1
ifdef LIBPCREDIR ifdef LIBPCREDIR
BASIC_CFLAGS += -I$(LIBPCREDIR)/include BASIC_CFLAGS += -I$(LIBPCREDIR)/include
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib) EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
@ -2239,8 +2241,9 @@ GIT-BUILD-OPTIONS: FORCE
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+ @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+ @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
@echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+ @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_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
@echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+ @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+ @echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
@echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+ @echo PAGER_ENV=\''$(subst ','\'',$(subst ','\'',$(PAGER_ENV)))'\' >>$@+
@ -2271,6 +2274,9 @@ endif
ifdef GIT_PERF_MAKE_OPTS ifdef GIT_PERF_MAKE_OPTS
@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@+ @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@+
endif endif
ifdef GIT_PERF_MAKE_COMMAND
@echo GIT_PERF_MAKE_COMMAND=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_COMMAND)))'\' >>$@+
endif
ifdef GIT_INTEROP_MAKE_OPTS ifdef GIT_INTEROP_MAKE_OPTS
@echo GIT_INTEROP_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_INTEROP_MAKE_OPTS)))'\' >>$@+ @echo GIT_INTEROP_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_INTEROP_MAKE_OPTS)))'\' >>$@+
endif endif

View file

@ -73,14 +73,14 @@ static pthread_mutex_t grep_mutex;
static inline void grep_lock(void) static inline void grep_lock(void)
{ {
if (num_threads) assert(num_threads);
pthread_mutex_lock(&grep_mutex); pthread_mutex_lock(&grep_mutex);
} }
static inline void grep_unlock(void) static inline void grep_unlock(void)
{ {
if (num_threads) assert(num_threads);
pthread_mutex_unlock(&grep_mutex); pthread_mutex_unlock(&grep_mutex);
} }
/* Signalled when a new work_item is added to todo. */ /* 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) if (num_threads < 0)
die(_("invalid number of threads specified (%d) for %s"), die(_("invalid number of threads specified (%d) for %s"),
num_threads, var); 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; return st;
@ -495,6 +506,8 @@ static void compile_submodule_options(const struct grep_opt *opt,
break; break;
case GREP_PATTERN_TYPE_UNSPECIFIED: case GREP_PATTERN_TYPE_UNSPECIFIED:
break; break;
default:
die("BUG: Added a new grep pattern type without updating switch statement");
} }
for (pattern = opt->pattern_list; pattern != NULL; for (pattern = opt->pattern_list; pattern != NULL;
@ -1229,6 +1242,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
else if (num_threads < 0) else if (num_threads < 0)
die(_("invalid number of threads specified (%d)"), num_threads); die(_("invalid number of threads specified (%d)"), num_threads);
#else #else
if (num_threads)
warning(_("no threads support, ignoring --threads"));
num_threads = 0; num_threads = 0;
#endif #endif

View file

@ -2483,8 +2483,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
die("invalid number of threads specified (%d)", die("invalid number of threads specified (%d)",
delta_search_threads); delta_search_threads);
#ifdef NO_PTHREADS #ifdef NO_PTHREADS
if (delta_search_threads != 1) if (delta_search_threads != 1) {
warning("no threads support, ignoring %s", k); warning("no threads support, ignoring %s", k);
delta_search_threads = 0;
}
#endif #endif
return 0; return 0;
} }

View 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]), AS_HELP_STRING([], [ARG can be prefix for openssl library and headers]),
GIT_PARSE_WITH([openssl])) GIT_PARSE_WITH([openssl]))
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be # Define USE_LIBPCRE if you have and want to use libpcre. Various
# able to use Perl-compatible regular expressions. # 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 # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
# /foo/bar/include and /foo/bar/lib directories. # /foo/bar/include and /foo/bar/lib directories.
@ -499,8 +501,10 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
GIT_CONF_SUBST([NO_OPENSSL]) GIT_CONF_SUBST([NO_OPENSSL])
# #
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be # Define USE_LIBPCRE if you have and want to use libpcre. Various
# able to use Perl-compatible regular expressions. # 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 if test -n "$USE_LIBPCRE"; then

110
grep.c
View file

@ -178,26 +178,23 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
case GREP_PATTERN_TYPE_BRE: case GREP_PATTERN_TYPE_BRE:
opt->fixed = 0; opt->fixed = 0;
opt->pcre = 0; opt->pcre1 = 0;
opt->regflags &= ~REG_EXTENDED;
break; break;
case GREP_PATTERN_TYPE_ERE: case GREP_PATTERN_TYPE_ERE:
opt->fixed = 0; opt->fixed = 0;
opt->pcre = 0; opt->pcre1 = 0;
opt->regflags |= REG_EXTENDED; opt->regflags |= REG_EXTENDED;
break; break;
case GREP_PATTERN_TYPE_FIXED: case GREP_PATTERN_TYPE_FIXED:
opt->fixed = 1; opt->fixed = 1;
opt->pcre = 0; opt->pcre1 = 0;
opt->regflags &= ~REG_EXTENDED;
break; break;
case GREP_PATTERN_TYPE_PCRE: case GREP_PATTERN_TYPE_PCRE:
opt->fixed = 0; opt->fixed = 0;
opt->pcre = 1; opt->pcre1 = 1;
opt->regflags &= ~REG_EXTENDED;
break; break;
} }
} }
@ -324,8 +321,32 @@ static NORETURN void compile_regexp_failed(const struct grep_pat *p,
die("%s'%s': %s", where, p->pattern, error); die("%s'%s': %s", where, p->pattern, error);
} }
#ifdef USE_LIBPCRE static int is_fixed(const char *s, size_t len)
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt) {
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; const char *error;
int erroffset; 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 (opt->ignore_case) {
if (has_non_ascii(p->pattern)) if (has_non_ascii(p->pattern))
p->pcre_tables = pcre_maketables(); p->pcre1_tables = pcre_maketables();
options |= PCRE_CASELESS; options |= PCRE_CASELESS;
} }
if (is_utf8_locale() && has_non_ascii(p->pattern)) if (is_utf8_locale() && has_non_ascii(p->pattern))
options |= PCRE_UTF8; options |= PCRE_UTF8;
p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset, p->pcre1_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
p->pcre_tables); p->pcre1_tables);
if (!p->pcre_regexp) if (!p->pcre1_regexp)
compile_regexp_failed(p, error); compile_regexp_failed(p, error);
p->pcre_extra_info = pcre_study(p->pcre_regexp, 0, &error); p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
if (!p->pcre_extra_info && error) if (!p->pcre1_extra_info && error)
die("%s", 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) regmatch_t *match, int eflags)
{ {
int ovector[30], ret, flags = 0; 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) if (eflags & REG_NOTBOL)
flags |= PCRE_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)); 0, flags, ovector, ARRAY_SIZE(ovector));
if (ret < 0 && ret != PCRE_ERROR_NOMATCH) if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
die("pcre_exec failed with error code %d", ret); 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; 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->pcre1_regexp);
pcre_free(p->pcre_extra_info); pcre_free(p->pcre1_extra_info);
pcre_free((void *)p->pcre_tables); pcre_free((void *)p->pcre1_tables);
} }
#else /* !USE_LIBPCRE */ #else /* !USE_LIBPCRE1 */
static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt) 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"); 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) regmatch_t *match, int eflags)
{ {
return 1; return 1;
} }
static void free_pcre_regexp(struct grep_pat *p) static void free_pcre1_regexp(struct grep_pat *p)
{ {
} }
#endif /* !USE_LIBPCRE */ #endif /* !USE_LIBPCRE1 */
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;
}
static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt) static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
{ {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int err; int err;
int regflags; int regflags = opt->regflags;
basic_regex_quote_buf(&sb, p->pattern); basic_regex_quote_buf(&sb, p->pattern);
regflags = opt->regflags & ~REG_EXTENDED;
if (opt->ignore_case) if (opt->ignore_case)
regflags |= REG_ICASE; regflags |= REG_ICASE;
err = regcomp(&p->regexp, sb.buf, regflags); 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 * simple string match using kws. p->fixed tells us if we
* want to use kws. * 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; p->fixed = !icase || ascii_only;
else else
p->fixed = 0; p->fixed = 0;
@ -475,8 +479,8 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
return; return;
} }
if (opt->pcre) { if (opt->pcre1) {
compile_pcre_regexp(p, opt); compile_pcre1_regexp(p, opt);
return; return;
} }
@ -832,8 +836,8 @@ void free_grep_patterns(struct grep_opt *opt)
case GREP_PATTERN_BODY: case GREP_PATTERN_BODY:
if (p->kws) if (p->kws)
kwsfree(p->kws); kwsfree(p->kws);
else if (p->pcre_regexp) else if (p->pcre1_regexp)
free_pcre_regexp(p); free_pcre1_regexp(p);
else else
regfree(&p->regexp); regfree(&p->regexp);
free(p->pattern); free(p->pattern);
@ -912,8 +916,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
if (p->fixed) if (p->fixed)
hit = !fixmatch(p, line, eol, match); hit = !fixmatch(p, line, eol, match);
else if (p->pcre_regexp) else if (p->pcre1_regexp)
hit = !pcrematch(p, line, eol, match, eflags); hit = !pcre1match(p, line, eol, match, eflags);
else else
hit = !regexec_buf(&p->regexp, line, eol - line, 1, match, hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
eflags); eflags);

10
grep.h
View file

@ -1,7 +1,7 @@
#ifndef GREP_H #ifndef GREP_H
#define GREP_H #define GREP_H
#include "color.h" #include "color.h"
#ifdef USE_LIBPCRE #ifdef USE_LIBPCRE1
#include <pcre.h> #include <pcre.h>
#else #else
typedef int pcre; typedef int pcre;
@ -46,9 +46,9 @@ struct grep_pat {
size_t patternlen; size_t patternlen;
enum grep_header_field field; enum grep_header_field field;
regex_t regexp; regex_t regexp;
pcre *pcre_regexp; pcre *pcre1_regexp;
pcre_extra *pcre_extra_info; pcre_extra *pcre1_extra_info;
const unsigned char *pcre_tables; const unsigned char *pcre1_tables;
kwset_t kws; kwset_t kws;
unsigned fixed:1; unsigned fixed:1;
unsigned ignore_case:1; unsigned ignore_case:1;
@ -111,7 +111,7 @@ struct grep_opt {
int allow_textconv; int allow_textconv;
int extended; int extended;
int use_reflog_filter; int use_reflog_filter;
int pcre; int pcre1;
int relative; int relative;
int pathname; int pathname;
int null_following_name; int null_following_name;

View file

@ -2026,6 +2026,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) { } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE; revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_ERE;
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
revs->grep_filter.ignore_case = 1;
revs->grep_filter.regflags |= REG_ICASE; revs->grep_filter.regflags |= REG_ICASE;
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE); DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {

View file

@ -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 Test is not run by root user, and an attempt to write to an
unwritable file is expected to fail correctly. 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. that use git-grep --perl-regexp or git-grep -P in these.
- CASE_INSENSITIVE_FS - 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) Test is run on a filesystem which converts decomposed utf-8 (nfd)
to precomposed utf-8 (nfc). to precomposed utf-8 (nfc).
- PTHREADS
Git wasn't compiled with NO_PTHREADS=YesPlease.
Tips for Writing Tests Tips for Writing Tests
---------------------- ----------------------

View file

@ -60,7 +60,22 @@ You can set the following variables (also in your config.mak):
GIT_PERF_MAKE_OPTS GIT_PERF_MAKE_OPTS
Options to use when automatically building a git tree for 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_REPO
GIT_PERF_LARGE_REPO GIT_PERF_LARGE_REPO

View file

@ -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

View file

@ -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

56
t/perf/p7820-grep-engines.sh Executable file
View file

@ -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

View file

@ -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

View file

@ -24,6 +24,7 @@ run_one_dir () {
unpack_git_rev () { unpack_git_rev () {
rev=$1 rev=$1
echo "=== Unpacking $rev in build/$rev ==="
mkdir -p build/$rev mkdir -p build/$rev
(cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) | (cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) |
(cd build/$rev && tar x) (cd build/$rev && tar x)
@ -37,8 +38,16 @@ build_git_rev () {
cp "../../$config" "build/$rev/" cp "../../$config" "build/$rev/"
fi fi
done done
(cd build/$rev && make $GIT_PERF_MAKE_OPTS) || echo "=== Building $rev ==="
die "failed to build revision '$mydir'" (
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 () { run_dirs_helper () {

View file

@ -231,14 +231,47 @@ second
initial initial
EOF EOF
test_expect_success 'log --invert-grep --grep' ' test_expect_success 'log --invert-grep --grep' '
git log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual && # Fixed
test_cmp expect actual 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' ' test_expect_success 'log --invert-grep --grep -i' '
echo initial >expect && 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' ' test_expect_success 'log --grep option parsing' '
@ -256,13 +289,53 @@ test_expect_success 'log -i --grep' '
test_expect_success 'log --grep -i' ' test_expect_success 'log --grep -i' '
echo Second >expect && echo Second >expect &&
# Fixed
git log -1 --pretty="tformat:%s" --grep=sec -i >actual && 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' ' test_expect_success 'log -F -E --grep=<ere> uses ere' '
echo second >expect && 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 test_cmp expect actual
' '
@ -280,6 +353,81 @@ test_expect_success 'log with grep.patternType configuration and command line' '
test_cmp expect actual 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 cat > expect <<EOF
* Second * Second
* sixth * sixth

View file

@ -421,6 +421,42 @@ test_expect_success 'index-pack <pack> works in non-repo' '
test_path_is_file foo.idx 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! # WARNING!
# #

View file

@ -4,8 +4,43 @@ test_description='git grep in binary files'
. ./test-lib.sh . ./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' " test_expect_success 'setup' "
echo 'binaryQfile' | q_to_nul >a && echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a &&
git add a && git add a &&
git commit -m. git commit -m.
" "
@ -69,35 +104,71 @@ test_expect_failure 'git grep .fi a' '
git grep .fi a git grep .fi a
' '
test_expect_success 'git grep -F y<NUL>f a' " nul_match 1 '-F' 'yQf'
printf 'yQf' | q_to_nul >f && nul_match 0 '-F' 'yQx'
git grep -f f -F a 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'
test_expect_success 'git grep -F y<NUL>x a' " # Regex patterns that would match but shouldn't with -F
printf 'yQx' | q_to_nul >f && nul_match 0 '-F' 'yQ[f]'
test_must_fail git grep -f f -F a 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Ð'
test_expect_success 'git grep -Fi Y<NUL>f a' " # kwset is disabled on -i & non-ASCII. No way to match non-ASCII \0
printf 'YQf' | q_to_nul >f && # patterns case-insensitively.
git grep -f f -Fi a nul_match T1 '-i' 'ÆQÐ'
"
test_expect_success 'git grep -Fi Y<NUL>x a' " # \0 implicitly disables regexes. This is an undocumented internal
printf 'YQx' | q_to_nul >f && # limitation.
test_must_fail git grep -f f -Fi a 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[Ð]'
test_expect_success 'git grep y<NUL>f a' " # ... because of \0 implicitly disabling regexes regexes that
printf 'yQf' | q_to_nul >f && # should/shouldn't match don't do the right thing.
git grep -f f a nul_match T1 '' 'eQm.*cQ'
" nul_match T1 '-i' 'EQM.*cQ'
nul_match T0 '' 'eQm[*]c'
nul_match T0 '-i' 'EQM[*]C'
test_expect_success 'git grep y<NUL>x a' " # Due to the REG_STARTEND extension when kwset() is disabled on -i &
printf 'yQx' | q_to_nul >f && # non-ASCII the string will be matched in its entirety, but the
test_must_fail git grep -f f a # 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' ' test_expect_success 'grep respects binary diff attribute' '
echo text >t && echo text >t &&
@ -162,7 +233,7 @@ test_expect_success 'grep does not honor textconv' '
' '
test_expect_success 'grep --textconv honors textconv' ' test_expect_success 'grep --textconv honors textconv' '
echo "a:binaryQfile" >expect && echo "a:binaryQfileQm[*]cQ*æQð" >expect &&
git grep --textconv Qfile >actual && git grep --textconv Qfile >actual &&
test_cmp expect 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' ' 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 && git grep --textconv Qfile HEAD:a >actual &&
test_cmp expect actual test_cmp expect actual
' '

View file

@ -275,12 +275,16 @@ do
test_cmp expected actual 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 && echo "${HC}ab:a+b*c" >expected &&
git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual && git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual &&
test_cmp expected 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" ' test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" '
echo "${HC}ab:abc" >expected && echo "${HC}ab:abc" >expected &&
git \ git \
@ -771,6 +775,40 @@ test_expect_success 'grep -W with userdiff' '
test_cmp expected actual 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)' ' test_expect_success 'grep from a subdirectory to search wider area (1)' '
mkdir -p s && mkdir -p s &&
( (
@ -1053,16 +1091,24 @@ hello.c:int main(int argc, const char **argv)
hello.c: printf("Hello world.\n"); hello.c: printf("Hello world.\n");
EOF 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 && git grep --perl-regexp "\p{Ps}.*?\p{Pe}" hello.c >actual &&
test_cmp expected 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 && git grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
test_cmp expected 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' ' test_expect_success 'grep pattern with grep.extendedRegexp=true' '
>empty && >empty &&
test_must_fail git -c grep.extendedregexp=true \ 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_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 \ git -c grep.extendedregexp=true \
grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual && grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual &&
test_cmp expected 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+b*c"
echo "ab:a+bc" echo "ab:a+bc"
@ -1085,7 +1131,7 @@ test_expect_success LIBPCRE 'grep -P -v pattern' '
test_cmp expected actual test_cmp expected actual
' '
test_expect_success LIBPCRE 'grep -P -i pattern' ' test_expect_success PCRE 'grep -P -i pattern' '
cat >expected <<-EOF && cat >expected <<-EOF &&
hello.c: printf("Hello world.\n"); hello.c: printf("Hello world.\n");
EOF EOF
@ -1093,7 +1139,7 @@ test_expect_success LIBPCRE 'grep -P -i pattern' '
test_cmp expected actual 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"
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_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_expect_success 'grep -G invalidpattern properly dies ' '
test_must_fail git grep -G "a[" 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_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_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[" 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_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 && echo "d0:0" >expected &&
git grep -G -F -E -P "[\d]" d0 >actual && git grep -G -F -E -P "[\d]" d0 >actual &&
test_cmp expected 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 && echo "d0:0" >expected &&
git \ git \
-c grep.patterntype=fixed \ -c grep.patterntype=fixed \
@ -1208,7 +1261,7 @@ test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =
test_cmp expected actual 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 && echo "ab:a+b*c" >expected &&
git \ git \
-c grep.patterntype=fixed \ -c grep.patterntype=fixed \
@ -1343,12 +1396,12 @@ space: line with leading space2
space: line with leading space3 space: line with leading space3
EOF EOF
test_expect_success LIBPCRE 'grep -E "^ "' ' test_expect_success PCRE 'grep -E "^ "' '
git grep -E "^ " space >actual && git grep -E "^ " space >actual &&
test_cmp expected actual test_cmp expected actual
' '
test_expect_success LIBPCRE 'grep -P "^ "' ' test_expect_success PCRE 'grep -P "^ "' '
git grep -P "^ " space >actual && git grep -P "^ " space >actual &&
test_cmp expected actual test_cmp expected actual
' '

View file

@ -20,13 +20,13 @@ test_expect_success REGEX_LOCALE 'grep literal string, no -F' '
git grep -i "TILRAUN: HALLÓ HEIMUR!" 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 "TILRAUN: H.lló Heimur!" &&
git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && git grep --perl-regexp -i "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 && test_write_lines "TILRAUN: Hallóó Heimur!" >file2 &&
git add file2 && git add file2 &&
git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual && 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' ' test_expect_success REGEX_LOCALE 'grep literal string, with -F' '
git grep --debug -i -F "TILRAUN: Halló Heimur!" 2>&1 >/dev/null | git grep -i -F "TILRAUN: Halló Heimur!" &&
grep fixed >debug1 && git grep -i -F "TILRAUN: HALLÓ HEIMUR!"
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
' '
test_expect_success REGEX_LOCALE 'grep string with regex, with -F' ' test_expect_success REGEX_LOCALE 'grep string with regex, with -F' '
test_write_lines "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file && test_write_lines "TILRAUN: Halló Heimur [abc]!" >file3 &&
git add file3 &&
git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 >/dev/null | git grep -i -F "TILRAUN: Halló Heimur [abc]!" file3
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_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' ' test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' '

View file

@ -11,7 +11,7 @@ test_expect_success GETTEXT_ISO_LOCALE 'setup' '
export LC_ALL 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!" &&
git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!"
' '

View file

@ -9,13 +9,13 @@ submodules.
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup directory structure and submodule' ' test_expect_success 'setup directory structure and submodule' '
echo "foobar" >a && echo "(1|2)d(3|4)" >a &&
mkdir b && mkdir b &&
echo "bar" >b/b && echo "(3|4)" >b/b &&
git add a b && git add a b &&
git commit -m "add a and b" && git commit -m "add a and b" &&
git init submodule && git init submodule &&
echo "foobar" >submodule/a && echo "(1|2)d(3|4)" >submodule/a &&
git -C submodule add a && git -C submodule add a &&
git -C submodule commit -m "add a" && git -C submodule commit -m "add a" &&
git submodule add ./submodule && 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' ' test_expect_success 'grep correctly finds patterns in a submodule' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
a:foobar a:(1|2)d(3|4)
b/b:bar b/b:(3|4)
submodule/a:foobar submodule/a:(1|2)d(3|4)
EOF EOF
git grep -e "bar" --recurse-submodules >actual && git grep -e "(3|4)" --recurse-submodules >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'grep and basic pathspecs' ' test_expect_success 'grep and basic pathspecs' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
submodule/a:foobar submodule/a:(1|2)d(3|4)
EOF EOF
git grep -e. --recurse-submodules -- submodule >actual && 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' ' test_expect_success 'grep and nested submodules' '
git init submodule/sub && 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 add a &&
git -C submodule/sub commit -m "add a" && git -C submodule/sub commit -m "add a" &&
git -C submodule submodule add ./sub && git -C submodule submodule add ./sub &&
@ -54,117 +54,117 @@ test_expect_success 'grep and nested submodules' '
git commit -m "updated submodule" && git commit -m "updated submodule" &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
a:foobar a:(1|2)d(3|4)
b/b:bar b/b:(3|4)
submodule/a:foobar submodule/a:(1|2)d(3|4)
submodule/sub/a:foobar submodule/sub/a:(1|2)d(3|4)
EOF EOF
git grep -e "bar" --recurse-submodules >actual && git grep -e "(3|4)" --recurse-submodules >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'grep and multiple patterns' ' test_expect_success 'grep and multiple patterns' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
a:foobar a:(1|2)d(3|4)
submodule/a:foobar submodule/a:(1|2)d(3|4)
submodule/sub/a:foobar submodule/sub/a:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep and multiple patterns' ' test_expect_success 'grep and multiple patterns' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
b/b:bar b/b:(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'basic grep tree' ' test_expect_success 'basic grep tree' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:a:foobar HEAD:a:(1|2)d(3|4)
HEAD:b/b:bar HEAD:b/b:(3|4)
HEAD:submodule/a:foobar HEAD:submodule/a:(1|2)d(3|4)
HEAD:submodule/sub/a:foobar HEAD:submodule/sub/a:(1|2)d(3|4)
EOF EOF
git grep -e "bar" --recurse-submodules HEAD >actual && git grep -e "(3|4)" --recurse-submodules HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'grep tree HEAD^' ' test_expect_success 'grep tree HEAD^' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD^:a:foobar HEAD^:a:(1|2)d(3|4)
HEAD^:b/b:bar HEAD^:b/b:(3|4)
HEAD^:submodule/a:foobar HEAD^:submodule/a:(1|2)d(3|4)
EOF EOF
git grep -e "bar" --recurse-submodules HEAD^ >actual && git grep -e "(3|4)" --recurse-submodules HEAD^ >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'grep tree HEAD^^' ' test_expect_success 'grep tree HEAD^^' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD^^:a:foobar HEAD^^:a:(1|2)d(3|4)
HEAD^^:b/b:bar HEAD^^:b/b:(3|4)
EOF EOF
git grep -e "bar" --recurse-submodules HEAD^^ >actual && git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'grep tree and pathspecs' ' test_expect_success 'grep tree and pathspecs' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:submodule/a:foobar HEAD:submodule/a:(1|2)d(3|4)
HEAD:submodule/sub/a:foobar HEAD:submodule/sub/a:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep tree and pathspecs' ' test_expect_success 'grep tree and pathspecs' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:submodule/a:foobar HEAD:submodule/a:(1|2)d(3|4)
HEAD:submodule/sub/a:foobar HEAD:submodule/sub/a:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep tree and more pathspecs' ' test_expect_success 'grep tree and more pathspecs' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:submodule/a:foobar HEAD:submodule/a:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep tree and more pathspecs' ' test_expect_success 'grep tree and more pathspecs' '
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:submodule/sub/a:foobar HEAD:submodule/sub/a:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success !MINGW 'grep recurse submodule colon in name' ' test_expect_success !MINGW 'grep recurse submodule colon in name' '
git init parent && git init parent &&
test_when_finished "rm -rf 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 add "fi:le" &&
git -C parent commit -m "add fi:le" && git -C parent commit -m "add fi:le" &&
git init "su:b" && git init "su:b" &&
test_when_finished "rm -rf 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" add "fi:le" &&
git -C "su:b" commit -m "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" && git -C parent commit -m "add submodule" &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
fi:le:foobar fi:le:(1|2)d(3|4)
su:b/fi:le:foobar su:b/fi:le:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD:fi:le:foobar HEAD:fi:le:(1|2)d(3|4)
HEAD:su:b/fi:le:foobar HEAD:su:b/fi:le:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep history with moved submoules' ' test_expect_success 'grep history with moved submoules' '
git init parent && git init parent &&
test_when_finished "rm -rf 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 add file &&
git -C parent commit -m "add file" && git -C parent commit -m "add file" &&
git init sub && git init sub &&
test_when_finished "rm -rf 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 add file &&
git -C sub commit -m "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" && git -C parent commit -m "add submodule" &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
dir/sub/file:foobar dir/sub/file:(1|2)d(3|4)
file:foobar file:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
git -C parent mv dir/sub sub-moved && git -C parent mv dir/sub sub-moved &&
git -C parent commit -m "moved submodule" && git -C parent commit -m "moved submodule" &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
file:foobar file:(1|2)d(3|4)
sub-moved/file:foobar sub-moved/file:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
HEAD^:dir/sub/file:foobar HEAD^:dir/sub/file:(1|2)d(3|4)
HEAD^:file:foobar HEAD^:file:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep using relative path' ' test_expect_success 'grep using relative path' '
test_when_finished "rm -rf parent sub" && test_when_finished "rm -rf parent sub" &&
git init sub && git init sub &&
echo "foobar" >sub/file && echo "(1|2)d(3|4)" >sub/file &&
git -C sub add file && git -C sub add file &&
git -C sub commit -m "add file" && git -C sub commit -m "add file" &&
git init parent && git init parent &&
echo "foobar" >parent/file && echo "(1|2)d(3|4)" >parent/file &&
git -C parent add file && git -C parent add file &&
mkdir parent/src && 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 add src/file2 &&
git -C parent submodule add ../sub && git -C parent submodule add ../sub &&
git -C parent commit -m "add files and submodule" && git -C parent commit -m "add files and submodule" &&
# From top works # From top works
cat >expect <<-\EOF && cat >expect <<-\EOF &&
file:foobar file:(1|2)d(3|4)
src/file2:foobar src/file2:(1|2)d(3|4)
sub/file:foobar sub/file:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
# Relative path to top # Relative path to top
cat >expect <<-\EOF && cat >expect <<-\EOF &&
../file:foobar ../file:(1|2)d(3|4)
file2:foobar file2:(1|2)d(3|4)
../sub/file:foobar ../sub/file:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
# Relative path to submodule # Relative path to submodule
cat >expect <<-\EOF && cat >expect <<-\EOF &&
../sub/file:foobar ../sub/file:(1|2)d(3|4)
EOF 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_cmp expect actual
' '
test_expect_success 'grep from a subdir' ' test_expect_success 'grep from a subdir' '
test_when_finished "rm -rf parent sub" && test_when_finished "rm -rf parent sub" &&
git init sub && git init sub &&
echo "foobar" >sub/file && echo "(1|2)d(3|4)" >sub/file &&
git -C sub add file && git -C sub add file &&
git -C sub commit -m "add file" && git -C sub commit -m "add file" &&
git init parent && git init parent &&
mkdir parent/src && 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 add src/file &&
git -C parent submodule add ../sub src/sub && git -C parent submodule add ../sub src/sub &&
git -C parent submodule add ../sub sub && git -C parent submodule add ../sub sub &&
@ -286,19 +286,19 @@ test_expect_success 'grep from a subdir' '
# Verify grep from root works # Verify grep from root works
cat >expect <<-\EOF && cat >expect <<-\EOF &&
src/file:foobar src/file:(1|2)d(3|4)
src/sub/file:foobar src/sub/file:(1|2)d(3|4)
sub/file:foobar sub/file:(1|2)d(3|4)
EOF 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 && test_cmp expect actual &&
# Verify grep from a subdir works # Verify grep from a subdir works
cat >expect <<-\EOF && cat >expect <<-\EOF &&
file:foobar file:(1|2)d(3|4)
sub/file:foobar sub/file:(1|2)d(3|4)
EOF 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 test_cmp expect actual
' '
@ -313,4 +313,53 @@ test_incompatible_with_recurse_submodules ()
test_incompatible_with_recurse_submodules --untracked test_incompatible_with_recurse_submodules --untracked
test_incompatible_with_recurse_submodules --no-index 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 test_done

View file

@ -1018,8 +1018,9 @@ esac
( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1 ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1
test -z "$NO_PERL" && test_set_prereq PERL 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 -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 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
# Can we rely on git's output in the C locale? # Can we rely on git's output in the C locale?