grep: --exclude matches trailing parts of args

Problem reported by Vincent Lefevre in:
http://bugs.gnu.org/22144
* NEWS:
* doc/grep.texi (File and Directory Selection): Document this.
* src/grep.c (excluded_patterns, excluded_directory_patterns):
Now 2-element arrays, with one element for subfiles and another
for command-line args.  All uses changed.  This implements the change.
(exclude_options): New function.
* tests/include-exclude: Test the change.
This commit is contained in:
Paul Eggert 2015-12-28 01:04:18 -08:00
parent abc6e54e75
commit f9c58376ca
4 changed files with 58 additions and 29 deletions

5
NEWS
View File

@ -8,6 +8,11 @@ GNU grep NEWS -*- outline -*-
invalid UTF8 just before a match.
[bug introduced in grep-2.22]
--exclude and related options are now matched against trailing
parts of command-line arguments, not against the entire arguments.
This partly reverts the --exclude-related change in 2.22.
[bug introduced in grep-2.22]
* Noteworthy changes in release 2.22 (2015-11-01) [stable]

View File

@ -661,8 +661,10 @@ this is equivalent to the @option{-r} option.
@opindex --exclude
@cindex exclude files
@cindex searching directory trees
Skip files whose name matches the pattern @var{glob}, using wildcard
matching. When searching recursively, skip any subfile whose base
Skip any command-line file with a name suffix that matches the pattern
@var{glob}, using wildcard matching; a name suffix is either the whole
name, or any suffix starting after a @samp{/} and before a
non-@samp{/}. When searching recursively, skip any subfile whose base
name matches @var{glob}; the base name is the part after the last
@samp{/}. A pattern can use
@samp{*}, @samp{?}, and @samp{[}...@samp{]} as wildcards,
@ -679,9 +681,10 @@ under @option{--exclude}).
@item --exclude-dir=@var{glob}
@opindex --exclude-dir
@cindex exclude directories
Skip any directory whose name matches the pattern @var{glob}. When
searching recursively, skip any subdirectory whose base name matches
@var{glob}. Ignore any redundant trailing slashes in @var{glob}.
Skip any command-line directory with a name suffix that matches the
pattern @var{glob}. When searching recursively, skip any subdirectory
whose base name matches @var{glob}. Ignore any redundant trailing
slashes in @var{glob}.
@item -I
Process a binary file as if it did not contain matching data;

View File

@ -296,8 +296,8 @@ static const struct color_cap color_dict[] =
{ NULL, NULL, NULL }
};
static struct exclude *excluded_patterns;
static struct exclude *excluded_directory_patterns;
static struct exclude *excluded_patterns[2];
static struct exclude *excluded_directory_patterns[2];
/* Short options. */
static char const short_options[] =
"0123456789A:B:C:D:EFGHIPTUVX:abcd:e:f:hiLlm:noqRrsuvwxyZz";
@ -640,19 +640,30 @@ context_length_arg (char const *str, intmax_t *out)
}
}
/* Return the add_exclude options suitable for excluding a file name.
If COMMAND_LINE, it is a command-line file name. */
static int
exclude_options (bool command_line)
{
return EXCLUDE_WILDCARDS | (command_line ? 0 : EXCLUDE_ANCHORED);
}
/* Return true if the file with NAME should be skipped.
If COMMAND_LINE, it is a command-line argument.
If IS_DIR, it is a directory. */
static bool
skipped_file (char const *name, bool command_line, bool is_dir)
{
return (is_dir
? (directories == SKIP_DIRECTORIES
|| (! (command_line && omit_dot_slash)
&& excluded_directory_patterns
&& excluded_file_name (excluded_directory_patterns, name)))
: (excluded_patterns
&& excluded_file_name (excluded_patterns, name)));
struct exclude **pats;
if (! is_dir)
pats = excluded_patterns;
else if (directories == SKIP_DIRECTORIES)
return true;
else if (command_line && omit_dot_slash)
return false;
else
pats = excluded_directory_patterns;
return pats[command_line] && excluded_file_name (pats[command_line], name);
}
/* Hairy buffering mechanism for grep. The intent is to keep
@ -2446,28 +2457,36 @@ main (int argc, char **argv)
case EXCLUDE_OPTION:
case INCLUDE_OPTION:
if (!excluded_patterns)
excluded_patterns = new_exclude ();
add_exclude (excluded_patterns, optarg,
(EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS
| (opt == INCLUDE_OPTION ? EXCLUDE_INCLUDE : 0)));
for (int cmd = 0; cmd < 2; cmd++)
{
if (!excluded_patterns[cmd])
excluded_patterns[cmd] = new_exclude ();
add_exclude (excluded_patterns[cmd], optarg,
((opt == INCLUDE_OPTION ? EXCLUDE_INCLUDE : 0)
| exclude_options (cmd)));
}
break;
case EXCLUDE_FROM_OPTION:
if (!excluded_patterns)
excluded_patterns = new_exclude ();
if (add_exclude_file (add_exclude, excluded_patterns, optarg,
EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS, '\n') != 0)
for (int cmd = 0; cmd < 2; cmd++)
{
error (EXIT_TROUBLE, errno, "%s", optarg);
if (!excluded_patterns[cmd])
excluded_patterns[cmd] = new_exclude ();
if (add_exclude_file (add_exclude, excluded_patterns[cmd],
optarg, exclude_options (cmd), '\n')
!= 0)
error (EXIT_TROUBLE, errno, "%s", optarg);
}
break;
case EXCLUDE_DIRECTORY_OPTION:
if (!excluded_directory_patterns)
excluded_directory_patterns = new_exclude ();
strip_trailing_slashes (optarg);
add_exclude (excluded_directory_patterns, optarg,
EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS);
for (int cmd = 0; cmd < 2; cmd++)
{
if (!excluded_directory_patterns[cmd])
excluded_directory_patterns[cmd] = new_exclude ();
add_exclude (excluded_directory_patterns[cmd], optarg,
exclude_options (cmd));
}
break;
case GROUP_SEPARATOR_OPTION:

View File

@ -66,9 +66,11 @@ for exclude in 'x' 'x*'; do
grep -rl --exclude-dir="$exclude" . x > out
test $? -eq 1 || fail=1
compare /dev/null out || fail=1
done
for exclude in 'x' 'x*' './x' './x*'; do
grep -rl --exclude-dir="$exclude" . ./x | sort > out || fail=1
compare exp-dotnames out || fail=1
compare /dev/null out || fail=1
done
Exit $fail