cli: add --no-ignore-exclude flag

This commit adds a new --no-ignore-exclude flag that permits disabling
the use of .git/info/exclude filtering. Local exclusions are manual
configurations to a repository and are not shared, so it is sometimes
useful to disable to get a consistent view of a repository.

This also adds a new section to the man page that describes automatic
filtering.

Closes #1420
This commit is contained in:
Naveen Nathan 2019-11-07 11:23:57 +11:00 committed by Andrew Gallant
parent 804b43ecd8
commit 297b428c8c
6 changed files with 115 additions and 1 deletions

View File

@ -23,6 +23,8 @@ Feature enhancements:
Add `--include-zero` flag that shows files searched without matches.
* [FEATURE #1390](https://github.com/BurntSushi/ripgrep/pull/1390):
Add `--no-context-separator` flag that always hides context separators.
* [FEATURE #1420](https://github.com/BurntSushi/ripgrep/pull/1420):
Add `--no-ignore-exclude` to disregard rules in `.git/info/exclude` files.
Bug fixes:

View File

@ -129,6 +129,10 @@ _rg() {
'--ignore-file-case-insensitive[process ignore files case insensitively]'
$no'--no-ignore-file-case-insensitive[process ignore files case sensitively]'
+ '(ignore-exclude)' # Local exclude (ignore)-file options
"--no-ignore-exclude[don't respect local exclude (ignore) files]"
$no'--ignore-exclude[respect local exclude (ignore) files]'
+ '(ignore-global)' # Global ignore-file options
"--no-ignore-global[don't respect global ignore files]"
$no'--ignore-global[respect global ignore files]'

View File

@ -104,6 +104,76 @@ was found. In summary:
unable to read a file).
AUTOMATIC FILTERING
-------------------
TL;DR - To disable automatic filtering, use 'rg -uuu'.
One of ripgrep's most important features is its automatic smart filtering.
It is the most apparent differentiating feature between ripgrep and other tools
like 'grep'. As such, its behavior may be surprising to users that aren't
expecting it.
ripgrep does four types of filtering automatically:
1. Files and directories that match ignore rules are not searched.
2. Hidden files and directories are not searched.
3. Binary files (files with a 'NUL' byte) are not searched.
4. Symbolic links are not followed.
The first type of filtering is the most sophisticated. ripgrep will attempt to
respect your gitignore rules as faithfully as possible. In particular, this
includes the following:
* Any global rules, e.g., in '$HOME/.config/git/ignore'.
* Any rules in '.gitignore'.
* Any local rules, e.g., in '.git/info/exclude'.
In some cases, ripgrep and git will not always be in sync in terms of which
files are ignored. For example, a file that is ignored via '.gitignore' but is
tracked by git would not be searched by ripgrep even though git tracks it. This
is unlikely to ever be fixed. Instead, you should either make sure your exclude
rules match the files you track precisely, or otherwise use 'git grep' for
search.
Additional ignore rules can be provided outside of a git context:
* Any rules in '.ignore'.
* Any rules in '.rgignore'.
* Any rules in files specified with the '--ignore-file' flag.
The precedence of ignore rules is as follows, with later items overriding
earlier items:
* Files given by '--ignore-file'.
* Global gitignore rules, e.g., from '$HOME/.config/git/ignore'.
* Local rules from '.git/info/exclude'.
* Rules from '.gitignore'.
* Rules from '.ignore'.
* Rules from '.rgignore'.
So for example, if 'foo' were in a '.gitignore' and '!foo' were in an
'.rgignore', then 'foo' would not be ignored since '.rgignore' takes precedence
over '.gitignore'.
Each of the types of filtering can be configured via command line flags:
* There are several flags starting with '--no-ignore' that toggle which,
if any, ignore rules are respected. '--no-ignore' by itself will disable
all of them.
* '--hidden' will force ripgrep to search hidden files and directories.
* '--binary' will force ripgrep to search binary files.
* '-L/--follow' will force ripgrep to follow symlinks.
As a special short hand, the `-u` flag can be specified up to three times. Each
additional time incrementally decreases filtering:
* '-u' is equivalent to '--no-ignore'.
* '-uu' is equivalent to '--no-ignore --hidden'.
* '-uuu' is equivalent to '--no-ignore --hidden --binary'.
In particular, 'rg -uuu' should search the same exact content as 'grep -r'.
CONFIGURATION FILES
-------------------
ripgrep supports reading configuration files that change ripgrep's default

View File

@ -595,6 +595,7 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
flag_no_config(&mut args);
flag_no_ignore(&mut args);
flag_no_ignore_dot(&mut args);
flag_no_ignore_exclude(&mut args);
flag_no_ignore_global(&mut args);
flag_no_ignore_messages(&mut args);
flag_no_ignore_parent(&mut args);
@ -1769,6 +1770,26 @@ This flag can be disabled with the --ignore-dot flag.
args.push(arg);
}
fn flag_no_ignore_exclude(args: &mut Vec<RGArg>) {
const SHORT: &str = "Don't respect local exclusion files.";
const LONG: &str = long!("\
Don't respect ignore files that are manually configured for the repository
such as git's '.git/info/exclude'.
This flag can be disabled with the --ignore-exclude flag.
");
let arg = RGArg::switch("no-ignore-exclude")
.help(SHORT).long_help(LONG)
.overrides("ignore-exclude");
args.push(arg);
let arg = RGArg::switch("ignore-exclude")
.hidden()
.overrides("no-ignore-exclude");
args.push(arg);
}
fn flag_no_ignore_global(args: &mut Vec<RGArg>) {
const SHORT: &str = "Don't respect global ignore files.";
const LONG: &str = long!("\

View File

@ -881,7 +881,7 @@ impl ArgMatches {
.ignore(!self.no_ignore_dot())
.git_global(!self.no_ignore_vcs() && !self.no_ignore_global())
.git_ignore(!self.no_ignore_vcs())
.git_exclude(!self.no_ignore_vcs())
.git_exclude(!self.no_ignore_vcs() && !self.no_ignore_exclude())
.ignore_case_insensitive(self.ignore_file_case_insensitive());
if !self.no_ignore() {
builder.add_custom_ignore_filename(".rgignore");
@ -1231,6 +1231,11 @@ impl ArgMatches {
self.is_present("no-ignore-dot") || self.no_ignore()
}
/// Returns true if local exclude (ignore) files should be ignored.
fn no_ignore_exclude(&self) -> bool {
self.is_present("no-ignore-exclude") || self.no_ignore()
}
/// Returns true if global ignore files should be ignored.
fn no_ignore_global(&self) -> bool {
self.is_present("no-ignore-global") || self.no_ignore()

View File

@ -728,6 +728,18 @@ rgtest!(f1207_ignore_encoding, |dir: Dir, mut cmd: TestCommand| {
eqnice!("\u{FFFD}\u{FFFD}\x00b\n", cmd.stdout());
});
// See: https://github.com/BurntSushi/ripgrep/pull/1420
rgtest!(f1420_no_ignore_dot, |dir: Dir, mut cmd: TestCommand| {
dir.create_dir(".git/info");
dir.create(".git/info/exclude", "foo");
dir.create("bar", "");
dir.create("foo", "");
cmd.arg("--sort").arg("path").arg("--files");
eqnice!("bar\n", cmd.stdout());
eqnice!("bar\nfoo\n", cmd.arg("--no-ignore-exclude").stdout());
});
rgtest!(no_context_sep, |dir: Dir, mut cmd: TestCommand| {
dir.create("test", "foo\nctx\nbar\nctx\nfoo\nctx");
cmd.args(&[