feat(config): Find config for each path passed in

This commit is contained in:
Ed Page 2019-08-07 10:16:57 -05:00
parent ad4c6dcd77
commit 87015d3522
2 changed files with 65 additions and 29 deletions

View file

@ -57,6 +57,14 @@ impl Config {
Ok(content)
}
pub fn derive(cwd: &std::path::Path) -> Result<Self, failure::Error> {
if let Some(path) = find_project_file(cwd.to_owned(), "typos.toml") {
Self::from_file(&path)
} else {
Ok(Default::default())
}
}
pub fn update(&mut self, source: &dyn ConfigSource) {
if let Some(source) = source.ignore_hidden() {
self.ignore_hidden = Some(source);
@ -138,3 +146,17 @@ impl ConfigSource for Config {
self.ignore_parent
}
}
fn find_project_file(dir: std::path::PathBuf, name: &str) -> Option<std::path::PathBuf> {
let mut file_path = dir;
file_path.push(name);
while !file_path.exists() {
file_path.pop(); // filename
let hit_bottom = !file_path.pop();
if hit_bottom {
return None;
}
file_path.push(name);
}
Some(file_path)
}

View file

@ -46,6 +46,10 @@ struct Options {
/// Custom config file
custom_config: Option<std::path::PathBuf>,
#[structopt(long = "isolated")]
/// Ignore implicit configuration files.
isolated: bool,
#[structopt(long, raw(overrides_with = r#""check-filenames""#))]
/// Skip verifying spelling in file names.
no_check_filenames: bool,
@ -255,13 +259,6 @@ pub fn get_logging(level: log::Level) -> env_logger::Builder {
fn run() -> Result<i32, failure::Error> {
let options = Options::from_args().infer();
let mut config = config::Config::default();
if let Some(path) = options.custom_config.as_ref() {
let custom = config::Config::from_file(path)?;
config.update(&custom);
}
config.update(&options);
let mut builder = get_logging(options.verbose.log_level());
builder.init();
@ -282,30 +279,47 @@ fn run() -> Result<i32, failure::Error> {
.binary(binary)
.build(&dictionary, &parser);
let first_path = &options
.path
.get(0)
.expect("arg parsing enforces at least one");
let mut walk = ignore::WalkBuilder::new(first_path);
for path in &options.path[1..] {
walk.add(path);
let mut config = config::Config::default();
if let Some(path) = options.custom_config.as_ref() {
let custom = config::Config::from_file(path)?;
config.update(&custom);
}
walk.hidden(config.ignore_hidden())
.ignore(config.ignore_dot())
.git_global(config.ignore_global())
.git_ignore(config.ignore_vcs())
.git_exclude(config.ignore_vcs())
.parents(config.ignore_parent());
let config = config;
let mut typos_found = false;
for entry in walk.build() {
let entry = entry?;
if entry.file_type().map(|t| t.is_file()).unwrap_or(true) {
let explicit = entry.depth() == 0;
if checks.check_filename(entry.path(), options.format.report())? {
typos_found = true;
}
if checks.check_file(entry.path(), explicit, options.format.report())? {
typos_found = true;
for path in options.path.iter() {
let path = path.canonicalize()?;
let cwd = if path.is_file() {
path.parent().unwrap()
} else {
path.as_path()
};
let mut config = config.clone();
if !options.isolated {
let derived = config::Config::derive(cwd)?;
config.update(&derived);
}
config.update(&options);
let config = config;
let mut walk = ignore::WalkBuilder::new(path);
walk.hidden(config.ignore_hidden())
.ignore(config.ignore_dot())
.git_global(config.ignore_global())
.git_ignore(config.ignore_vcs())
.git_exclude(config.ignore_vcs())
.parents(config.ignore_parent());
for entry in walk.build() {
let entry = entry?;
if entry.file_type().map(|t| t.is_file()).unwrap_or(true) {
let explicit = entry.depth() == 0;
if checks.check_filename(entry.path(), options.format.report())? {
typos_found = true;
}
if checks.check_file(entry.path(), explicit, options.format.report())? {
typos_found = true;
}
}
}
}