From 5e832acdc49ecc717a27c5ab1ca1503374d930b7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 7 May 2017 16:44:03 +0900 Subject: [PATCH] Allow config-path to point to a file --- src/bin/rustfmt.rs | 62 ++++++++++++++++++++++++++++++---------------- src/config.rs | 26 ++++++++++++------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 45f695c64777..2c741934a5ea 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -98,6 +98,8 @@ fn apply_to(self, config: &mut Config) { } } +const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + /// Try to find a project file in the given directory and its parents. Returns the path of a the /// nearest project file if one exists, or `None` if no project file was found. fn lookup_project_file(dir: &Path) -> FmtResult> { @@ -109,8 +111,6 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { current = try!(fs::canonicalize(current)); - const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; - loop { for config_file_name in &CONFIG_FILE_NAMES { let config_file = current.join(config_file_name); @@ -136,6 +136,16 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { } } +fn open_config_file(file_path: &Path) -> FmtResult<(Config, Option)> { + let mut file = try!(File::open(&file_path)); + let mut toml = String::new(); + try!(file.read_to_string(&mut toml)); + match Config::from_toml(&toml) { + Ok(cfg) => Ok((cfg, Some(file_path.to_path_buf()))), + Err(err) => Err(FmtError::from(err)), + } +} + /// Resolve the config for input in `dir`. /// /// Returns the `Config` to use, and the path of the project file if there was @@ -145,14 +155,7 @@ fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { if path.is_none() { return Ok((Config::default(), None)); } - let path = path.unwrap(); - let mut file = try!(File::open(&path)); - let mut toml = String::new(); - try!(file.read_to_string(&mut toml)); - match Config::from_toml(&toml) { - Ok(cfg) => Ok((cfg, Some(path))), - Err(err) => Err(FmtError::from(err)), - } + open_config_file(&path.unwrap()) } /// read the given config file path recursively if present else read the project file path @@ -161,7 +164,7 @@ fn match_cli_path_or_file(config_path: Option, -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { - let (toml, path) = try!(resolve_config(config_file.as_ref())); + let (toml, path) = try!(open_config_file(config_file.as_ref())); if path.is_some() { return Ok((toml, path)); } @@ -246,7 +249,7 @@ fn execute(opts: &Options) -> FmtResult { let mut path = None; // Load the config path file if provided if let Some(config_file) = config_path { - let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref())?; + let (cfg_tmp, path_tmp) = open_config_file(config_file.as_ref())?; config = cfg_tmp; path = path_tmp; }; @@ -325,7 +328,7 @@ fn main() { } fn print_usage(opts: &Options, reason: &str) { - let reason = format!("{}\nusage: {} [options] ...", + let reason = format!("{}\n\nusage: {} [options] ...", reason, env::args_os().next().unwrap().to_string_lossy()); println!("{}", opts.usage(&reason)); @@ -354,16 +357,31 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::Version); } + let config_path_not_found = |path: &str| -> FmtResult { + Err(FmtError::from(format!("Error: unable to find a config file for the given path: `{}`", + path))) + }; + // Read the config_path and convert to parent dir if a file is provided. - let config_path: Option = matches - .opt_str("config-path") - .map(PathBuf::from) - .and_then(|dir| { - if dir.is_file() { - return dir.parent().map(|v| v.into()); - } - Some(dir) - }); + // If a config file cannot be found from the given path, return error. + let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { + Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), + Some(ref path) if path.is_dir() => { + let mut config_file_path = None; + for config_file_name in &CONFIG_FILE_NAMES { + let temp_path = path.join(config_file_name); + if temp_path.is_file() { + config_file_path = Some(temp_path); + } + } + if config_file_path.is_some() { + config_file_path + } else { + return config_path_not_found(path.to_str().unwrap()); + } + } + path @ _ => path, + }; // if no file argument is supplied, read from stdin if matches.free.is_empty() { diff --git a/src/config.rs b/src/config.rs index 805581abb4ef..441f86f48cbf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -237,16 +237,24 @@ fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config { } pub fn from_toml(toml: &str) -> Result { - let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); + let parsed: toml::Value = + toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; let mut err: String = String::new(); - for (key, _) in parsed.as_table().expect("Parsed config was not table") { - match &**key { - $( - stringify!($i) => (), - )+ - _ => { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for (key, _) in table { + match &**key { + $( + stringify!($i) => (), + )+ + _ => { + let msg = + &format!("Warning: Unknown configuration option `{}`\n", + key); + err.push_str(msg) + } } } }