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) 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) { pub fn update(&mut self, source: &dyn ConfigSource) {
if let Some(source) = source.ignore_hidden() { if let Some(source) = source.ignore_hidden() {
self.ignore_hidden = Some(source); self.ignore_hidden = Some(source);
@ -138,3 +146,17 @@ impl ConfigSource for Config {
self.ignore_parent 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 file
custom_config: Option<std::path::PathBuf>, custom_config: Option<std::path::PathBuf>,
#[structopt(long = "isolated")]
/// Ignore implicit configuration files.
isolated: bool,
#[structopt(long, raw(overrides_with = r#""check-filenames""#))] #[structopt(long, raw(overrides_with = r#""check-filenames""#))]
/// Skip verifying spelling in file names. /// Skip verifying spelling in file names.
no_check_filenames: bool, no_check_filenames: bool,
@ -255,13 +259,6 @@ pub fn get_logging(level: log::Level) -> env_logger::Builder {
fn run() -> Result<i32, failure::Error> { fn run() -> Result<i32, failure::Error> {
let options = Options::from_args().infer(); 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()); let mut builder = get_logging(options.verbose.log_level());
builder.init(); builder.init();
@ -282,21 +279,37 @@ fn run() -> Result<i32, failure::Error> {
.binary(binary) .binary(binary)
.build(&dictionary, &parser); .build(&dictionary, &parser);
let first_path = &options let mut config = config::Config::default();
.path if let Some(path) = options.custom_config.as_ref() {
.get(0) let custom = config::Config::from_file(path)?;
.expect("arg parsing enforces at least one"); config.update(&custom);
let mut walk = ignore::WalkBuilder::new(first_path);
for path in &options.path[1..] {
walk.add(path);
} }
let config = config;
let mut typos_found = false;
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()) walk.hidden(config.ignore_hidden())
.ignore(config.ignore_dot()) .ignore(config.ignore_dot())
.git_global(config.ignore_global()) .git_global(config.ignore_global())
.git_ignore(config.ignore_vcs()) .git_ignore(config.ignore_vcs())
.git_exclude(config.ignore_vcs()) .git_exclude(config.ignore_vcs())
.parents(config.ignore_parent()); .parents(config.ignore_parent());
let mut typos_found = false;
for entry in walk.build() { for entry in walk.build() {
let entry = entry?; let entry = entry?;
if entry.file_type().map(|t| t.is_file()).unwrap_or(true) { if entry.file_type().map(|t| t.is_file()).unwrap_or(true) {
@ -309,6 +322,7 @@ fn run() -> Result<i32, failure::Error> {
} }
} }
} }
}
if typos_found { if typos_found {
Ok(1) Ok(1)