Skip to content

Commit ee32615

Browse files
committed
Merge pull request #792 from kamalmarhubi/project-file-lookup-error-handling
bin: Improve error handling in project file lookup
2 parents 86572d4 + 0f254bb commit ee32615

File tree

1 file changed

+42
-28
lines changed

1 file changed

+42
-28
lines changed

src/bin/rustfmt.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustfmt::config::{Config, WriteMode};
2222

2323
use std::env;
2424
use std::fs::{self, File};
25-
use std::io::{self, Read, Write};
25+
use std::io::{self, ErrorKind, Read, Write};
2626
use std::path::{Path, PathBuf};
2727

2828
use getopts::{Matches, Options};
@@ -43,39 +43,56 @@ enum Operation {
4343
Stdin(String, WriteMode),
4444
}
4545

46-
/// Try to find a project file in the input file directory and its parents.
47-
fn lookup_project_file(input_file: &Path) -> io::Result<PathBuf> {
48-
let mut current = if input_file.is_relative() {
49-
try!(env::current_dir()).join(input_file)
46+
/// Try to find a project file in the given directory and its parents. Returns the path of a the
47+
/// nearest project file if one exists, or `None` if no project file was found.
48+
fn lookup_project_file(dir: &Path) -> io::Result<Option<PathBuf>> {
49+
let mut current = if dir.is_relative() {
50+
try!(env::current_dir()).join(dir)
5051
} else {
51-
input_file.to_path_buf()
52+
dir.to_path_buf()
5253
};
5354

5455
current = try!(fs::canonicalize(current));
5556

5657
loop {
5758
let config_file = current.join("rustfmt.toml");
58-
if let Ok(md) = fs::metadata(&config_file) {
59-
// Properly handle unlikely situation of a directory named `rustfmt.toml`.
60-
if md.is_file() {
61-
return Ok(config_file);
59+
match fs::metadata(&config_file) {
60+
Ok(md) => {
61+
// Properly handle unlikely situation of a directory named `rustfmt.toml`.
62+
if md.is_file() {
63+
return Ok(Some(config_file));
64+
}
65+
}
66+
// If it's not found, we continue searching; otherwise something went wrong and we
67+
// return the error.
68+
Err(e) => {
69+
if e.kind() != ErrorKind::NotFound {
70+
return Err(e);
71+
}
6272
}
6373
}
6474

6575
// If the current directory has no parent, we're done searching.
6676
if !current.pop() {
67-
return Err(io::Error::new(io::ErrorKind::NotFound, "Config not found"));
77+
return Ok(None);
6878
}
6979
}
7080
}
7181

72-
/// Try to find a project file. If it's found, read it.
73-
fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, String)> {
74-
let path = try!(lookup_project_file(input_file));
82+
/// Resolve the config for input in `dir`.
83+
///
84+
/// Returns the `Config` to use, and the path of the project file if there was
85+
/// one.
86+
fn resolve_config(dir: &Path) -> io::Result<(Config, Option<PathBuf>)> {
87+
let path = try!(lookup_project_file(dir));
88+
if path.is_none() {
89+
return Ok((Config::default(), None));
90+
}
91+
let path = path.unwrap();
7592
let mut file = try!(File::open(&path));
7693
let mut toml = String::new();
7794
try!(file.read_to_string(&mut toml));
78-
Ok((path, toml))
95+
Ok((Config::from_toml(&toml), Some(path)))
7996
}
8097

8198
fn update_config(config: &mut Config, matches: &Matches) {
@@ -127,25 +144,22 @@ fn execute() -> i32 {
127144
}
128145
Operation::Stdin(input, write_mode) => {
129146
// try to read config from local directory
130-
let config = match lookup_and_read_project_file(&Path::new(".")) {
131-
Ok((_, toml)) => Config::from_toml(&toml),
132-
Err(_) => Default::default(),
133-
};
147+
let (config, _) = resolve_config(&env::current_dir().unwrap())
148+
.expect("Error resolving config");
134149

135150
run_from_stdin(input, write_mode, &config);
136151
0
137152
}
138153
Operation::Format(files, write_mode) => {
139154
for file in files {
140-
let mut config = match lookup_and_read_project_file(&file) {
141-
Ok((path, toml)) => {
142-
println!("Using rustfmt config file {} for {}",
143-
path.display(),
144-
file.display());
145-
Config::from_toml(&toml)
146-
}
147-
Err(_) => Default::default(),
148-
};
155+
let (mut config, path) = resolve_config(file.parent().unwrap())
156+
.expect(&format!("Error resolving config for {}",
157+
file.display()));
158+
if let Some(path) = path {
159+
println!("Using rustfmt config file {} for {}",
160+
path.display(),
161+
file.display());
162+
}
149163

150164
update_config(&mut config, &matches);
151165
run(&file, write_mode, &config);

0 commit comments

Comments
 (0)