Make --no-ignore imply all other --no-ignore- flags (#588)

* Make --no-ignore imply all other --no-ignore- flags

And add --no-ignore-dot to only disable .ignore files, matching ripgrep.

Fixes #585.

* Cosmetic code updates for consistency

* Update CLI help text in README

* Update src/utils/fs.rs

Co-authored-by: Liwen Guo <lg@livven.me>

Co-authored-by: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com>
This commit is contained in:
Liwen Guo 2020-09-20 15:30:35 +02:00 committed by GitHub
parent 82429f5c32
commit a6fa401dc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 188 additions and 25 deletions

View file

@ -229,9 +229,12 @@ FLAGS:
-h, --help Prints help information
--hidden Count hidden files.
-l, --languages Prints out supported languages and their extensions.
--no-ignore Don't respect ignore files.
--no-ignore-parent Don't respect ignore files in parent directories.
--no-ignore-vcs Don't respect VCS ignore files.
--no-ignore Don't respect ignore files (.gitignore, .ignore, etc.). This implies --no-ignore-parent,
--no-ignore-dot, and --no-ignore-vcs.
--no-ignore-dot Don't respect .ignore and .tokeignore files, including those in parent directories.
--no-ignore-parent Don't respect ignore files (.gitignore, .ignore, etc.) in parent directories.
--no-ignore-vcs Don't respect VCS ignore files (.gitignore, .hgignore, etc.), including those in parent
directories.
-V, --version Prints version information
-v, --verbose Set log output level:
1: to show unknown file extensions,
@ -240,7 +243,7 @@ FLAGS:
OPTIONS:
-c, --columns <columns> Sets a strict column width of the output, only available for terminal output.
-e, --exclude <exclude>... Ignore all files & directories containing the word.
-e, --exclude <exclude>... Ignore all files & directories matching the pattern.
-i, --input <file_input> Gives statistics from a previous tokei run. Can be given a file path, or "stdin" to
read from stdin.
-o, --output <output> Outputs Tokei in a specific format. Compile with additional features for more format
@ -249,7 +252,7 @@ OPTIONS:
-t, --type <types> Filters output by language type, seperated by a comma. i.e. -t=Rust,Markdown
ARGS:
<input>... The input file(s)/directory(ies) to be counted.
<input>... The path(s) to the file or directory to be counted.
```
## Badges

View file

@ -14,6 +14,7 @@ pub struct Cli<'a> {
pub hidden: bool,
pub no_ignore: bool,
pub no_ignore_parent: bool,
pub no_ignore_dot: bool,
pub no_ignore_vcs: bool,
pub output: Option<Format>,
pub print_languages: bool,
@ -57,11 +58,17 @@ impl<'a> Cli<'a> {
conflicts_with[input]
"Prints out supported languages and their extensions.")
(@arg no_ignore: --("no-ignore")
"Don't respect ignore files.")
"Don't respect ignore files (.gitignore, .ignore, etc.). This implies \
--no-ignore-parent, --no-ignore-dot, and --no-ignore-vcs.")
(@arg no_ignore_parent: --("no-ignore-parent")
"Don't respect ignore files in parent directories.")
"Don't respect ignore files (.gitignore, .ignore, etc.) in parent \
directories.")
(@arg no_ignore_dot: --("no-ignore-dot")
"Don't respect .ignore and .tokeignore files, including those in \
parent directories.")
(@arg no_ignore_vcs: --("no-ignore-vcs")
"Don't respect VCS (.gitignore, .hgignore, etc) ignore files.")
"Don't respect VCS ignore files (.gitignore, .hgignore, etc.), including \
those in parent directories.")
(@arg output: -o --output
// `all` is used so to fail later with a better error
possible_values(Format::all())
@ -95,6 +102,7 @@ impl<'a> Cli<'a> {
let hidden = matches.is_present("hidden");
let no_ignore = matches.is_present("no_ignore");
let no_ignore_parent = matches.is_present("no_ignore_parent");
let no_ignore_dot = matches.is_present("no_ignore_dot");
let no_ignore_vcs = matches.is_present("no_ignore_vcs");
let print_languages = matches.is_present("languages");
let verbose = matches.occurrences_of("verbose");
@ -135,6 +143,7 @@ impl<'a> Cli<'a> {
matches,
no_ignore,
no_ignore_parent,
no_ignore_dot,
no_ignore_vcs,
output,
print_languages,
@ -181,6 +190,7 @@ impl<'a> Cli<'a> {
/// #### Shared options
/// * `no_ignore`
/// * `no_ignore_parent`
/// * `no_ignore_dot`
/// * `no_ignore_vcs`
/// * `types`
pub fn override_config(&mut self, mut config: Config) -> Config {
@ -202,6 +212,12 @@ impl<'a> Cli<'a> {
config.no_ignore_parent
};
config.no_ignore_dot = if self.no_ignore_dot {
Some(true)
} else {
config.no_ignore_dot
};
config.no_ignore_vcs = if self.no_ignore_vcs {
Some(true)
} else {

View file

@ -23,11 +23,17 @@ pub struct Config {
pub columns: Option<usize>,
/// Count hidden files and directories. *Default:* `false`.
pub hidden: Option<bool>,
/// Don't respect ignore files. *Default:* `false`.
/// Don't respect ignore files (.gitignore, .ignore, etc.). This implies --no-ignore-parent,
/// --no-ignore-dot, and --no-ignore-vcs. *Default:* `false`.
pub no_ignore: Option<bool>,
/// Don't respect ignore files in parent directories. *Default:* `false`.
/// Don't respect ignore files (.gitignore, .ignore, etc.) in parent directories.
/// *Default:* `false`.
pub no_ignore_parent: Option<bool>,
/// Don't respect VCS ignore files. *Default:* `false`.
/// Don't respect .ignore and .tokeignore files, including those in parent directories.
/// *Default:* `false`.
pub no_ignore_dot: Option<bool>,
/// Don't respect VCS ignore files (.gitignore, .hgignore, etc.), including those in
/// parent directories. *Default:* `false`.
pub no_ignore_vcs: Option<bool>,
/// Whether to treat doc strings in languages as comments. *Default:*
/// `false`.
@ -107,6 +113,9 @@ impl Config {
no_ignore_parent: current_dir
.no_ignore_parent
.or(home_dir.no_ignore_parent.or(conf_dir.no_ignore_parent)),
no_ignore_dot: current_dir
.no_ignore_dot
.or(home_dir.no_ignore_dot.or(conf_dir.no_ignore_dot)),
no_ignore_vcs: current_dir
.no_ignore_vcs
.or(home_dir.no_ignore_vcs.or(conf_dir.no_ignore_vcs)),

View file

@ -37,22 +37,23 @@ pub fn get_all_files<A: AsRef<Path>>(
walker.overrides(overrides.build().expect("Excludes provided were invalid"));
}
// Flip the booleans as ignore's semantics are the opposite of our options.
let no_ignore_vcs = config.no_ignore_vcs.map(|b| !b).unwrap_or(true);
let ignore = config.no_ignore.map(|b| !b).unwrap_or(true);
let ignore_dot = ignore && config.no_ignore_dot.map(|b| !b).unwrap_or(true);
let ignore_vcs = ignore && config.no_ignore_vcs.map(|b| !b).unwrap_or(true);
// Custom ignore files always work even if the `ignore` option is false,
// so we only add if that option is not present.
if !config.no_ignore.unwrap_or(false) {
if ignore_dot {
walker.add_custom_ignore_filename(IGNORE_FILE);
}
walker
.git_exclude(no_ignore_vcs)
.git_global(no_ignore_vcs)
.git_ignore(no_ignore_vcs)
.git_exclude(ignore_vcs)
.git_global(ignore_vcs)
.git_ignore(ignore_vcs)
.hidden(config.hidden.map(|b| !b).unwrap_or(true))
.ignore(config.no_ignore.map(|b| !b).unwrap_or(true))
.parents(config.no_ignore_parent.map(|b| !b).unwrap_or(true));
.ignore(ignore_dot)
.parents(ignore && config.no_ignore_parent.map(|b| !b).unwrap_or(true));
walker.build_parallel().run(move || {
let tx = tx.clone();
@ -182,13 +183,11 @@ mod tests {
}
#[test]
fn no_ignore() {
fn no_ignore_implies_dot() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
//git2::Repository::init(dir.path()).expect("Couldn't create git repo.");
fs::write(dir.path().join(".ignore"), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
@ -213,9 +212,41 @@ mod tests {
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
fn no_ignore_implies_vcs_gitignore() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
git2::Repository::init(dir.path()).expect("Couldn't create git repo.");
fs::write(dir.path().join(".gitignore"), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_none());
config.no_ignore = Some(true);
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
fn no_ignore_parent() {
let parent_dir = TempDir::new().expect("Couldn't create temp dir");
let parent_dir = TempDir::new().expect("Couldn't create temp dir.");
let child_dir = parent_dir.path().join("child/");
let mut config = Config::default();
let mut languages = Languages::new();
@ -233,7 +264,7 @@ mod tests {
&config,
);
assert_eq!(None, languages.get(&LanguageType::Rust));
assert!(languages.get(LANGUAGE).is_none());
config.no_ignore_parent = Some(true);
@ -244,7 +275,90 @@ mod tests {
&config,
);
assert!(languages.get(&LanguageType::Rust).is_some());
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
fn no_ignore_dot() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
fs::write(dir.path().join(".ignore"), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_none());
config.no_ignore_dot = Some(true);
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
fn no_ignore_dot_still_vcs_gitignore() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
git2::Repository::init(dir.path()).expect("Couldn't create git repo.");
fs::write(dir.path().join(".gitignore"), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
config.no_ignore_dot = Some(true);
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_none());
}
#[test]
fn no_ignore_dot_includes_custom_ignore() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
fs::write(dir.path().join(IGNORE_FILE), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_none());
config.no_ignore_dot = Some(true);
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
@ -279,6 +393,27 @@ mod tests {
assert!(languages.get(LANGUAGE).is_some());
}
#[test]
fn no_ignore_vcs_gitignore_still_dot() {
let dir = TempDir::new().expect("Couldn't create temp dir.");
let mut config = Config::default();
let mut languages = Languages::new();
fs::write(dir.path().join(".ignore"), IGNORE_PATTERN).unwrap();
fs::write(dir.path().join(FILE_NAME), FILE_CONTENTS).unwrap();
config.no_ignore_vcs = Some(true);
super::get_all_files(
&[dir.path().to_str().unwrap()],
&[],
&mut languages,
&config,
);
assert!(languages.get(LANGUAGE).is_none());
}
#[test]
fn no_ignore_vcs_gitexclude() {
let dir = TempDir::new().expect("Couldn't create temp dir.");