Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 49 additions & 52 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,50 +354,7 @@ impl Config {
style_edition: Option<StyleEdition>,
version: Option<Version>,
) -> Result<(Config, Option<PathBuf>), Error> {
/// Try to find a project file in the given directory and its parents.
/// Returns the path of the nearest project file if one exists,
/// or `None` if no project file was found.
fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
let mut current = if dir.is_relative() {
env::current_dir()?.join(dir)
} else {
dir.to_path_buf()
};

current = fs::canonicalize(current)?;

loop {
match get_toml_path(&current) {
Ok(Some(path)) => return Ok(Some(path)),
Err(e) => return Err(e),
_ => (),
}

// If the current directory has no parent, we're done searching.
if !current.pop() {
break;
}
}

// If nothing was found, check in the home directory.
if let Some(home_dir) = dirs::home_dir() {
if let Some(path) = get_toml_path(&home_dir)? {
return Ok(Some(path));
}
}

// If none was found there either, check in the user's configuration directory.
if let Some(mut config_dir) = dirs::config_dir() {
config_dir.push("rustfmt");
if let Some(path) = get_toml_path(&config_dir)? {
return Ok(Some(path));
}
}

Ok(None)
}

match resolve_project_file(dir)? {
match resolve_project_file(dir).or_else(|_| config_from_user_dirs())? {
None => Ok((
Config::default_for_possible_style_edition(style_edition, edition, version),
None,
Expand Down Expand Up @@ -455,6 +412,53 @@ impl Config {
}
}

/// Looks for a configuration file in the given directory and its parents.
///
/// Returns the path of the configuration file nearest to that directory if one exists, or `None` if
/// none was found.
fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
let mut current = if dir.is_relative() {
env::current_dir()?.join(dir)
} else {
dir.to_path_buf()
};

current = fs::canonicalize(current)?;

loop {
match get_toml_path(&current) {
Ok(Some(path)) => return Ok(Some(path)),
Err(e) => return Err(e),
_ => (),
}

// If the current directory has no parent, we're done searching.
if !current.pop() {
break Ok(None);
}
}
}

/// Looks for a configuration file in the user's home directory and configuration directory.
///
/// Returns the path of the first configuration file found in that order, or `None` if none was
/// found.
fn config_from_user_dirs() -> Result<Option<PathBuf>, Error> {
for dir in [
dirs::home_dir(),
dirs::config_dir().map(|d| d.join("rustfmt")),
]
.iter()
.flatten()
{
if let Some(path) = get_toml_path(&dir)? {
return Ok(Some(path));
}
}

Ok(None)
}

/// Loads a config by checking the client-supplied options and if appropriate, the
/// file system (including searching the file system for overrides).
pub fn load_config<O: CliOptions>(
Expand Down Expand Up @@ -534,14 +538,7 @@ fn config_path(options: &dyn CliOptions) -> Result<Option<PathBuf>, Error> {
// If a config file cannot be found from the given path, return error.
match options.config_path() {
Some(path) if !path.exists() => config_path_not_found(path.to_str().unwrap()),
Some(path) if path.is_dir() => {
let config_file_path = get_toml_path(path)?;
if config_file_path.is_some() {
Ok(config_file_path)
} else {
config_path_not_found(path.to_str().unwrap())
}
}
Some(path) if path.is_dir() => resolve_project_file(path),
Some(path) => Ok(Some(
// Canonicalize only after checking above that the `path.exists()`.
path.canonicalize()?,
Expand Down
7 changes: 7 additions & 0 deletions tests/config/issue_4660/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions tests/config/issue_4660/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[workspace]
members = ["inner_lib"]
1 change: 1 addition & 0 deletions tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
disable_all_formatting = true
6 changes: 6 additions & 0 deletions tests/config/issue_4660/inner_bin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "inner_bin"
version = "0.1.0"
edition = "2021"

[dependencies]
1 change: 1 addition & 0 deletions tests/config/issue_4660/inner_bin/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main(){println!("Hello, world!")}
6 changes: 6 additions & 0 deletions tests/config/issue_4660/inner_lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "inner_lib"
version = "0.1.0"
edition = "2021"

[dependencies]
1 change: 1 addition & 0 deletions tests/config/issue_4660/inner_lib/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
disable_all_formatting = true
1 change: 1 addition & 0 deletions tests/config/issue_4660/inner_lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub fn add(left:u64,right:u64)->u64{left+right}
31 changes: 31 additions & 0 deletions tests/rustfmt/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,37 @@ fn rustfmt_error_improvement_regarding_invalid_toml() {
assert!(stderr.contains(&expected_error_message));
}

#[test]
fn config_path_walks_parent_directories_with_dir_name() {
let src_dir = "tests/config/issue_4660/inner_lib/src";
let src_file = src_dir.to_owned() + "/lib.rs";
let args = ["--config-path", src_dir, "--check", &src_file];
let (stdout, stderr) = rustfmt(&args);

assert_eq!(stderr, "");
// Due to `disable_all_formatting = true` in `tests/config/issue_4660/inner_lib/rustfmt.toml`,
// the source file should not be modified.
assert_eq!(stdout, "");
}

#[test]
fn config_path_does_not_walk_parent_directories_with_toml_name() {
let src_dir = "tests/config/issue_4660/inner_bin/src";
let toml_file = src_dir.to_owned() + "/.rustfmt.unstable.toml";
let src_file = src_dir.to_owned() + "/main.rs";
let args = ["--config-path", &toml_file, "--check", &src_file];
let (stdout, stderr) = rustfmt(&args);

assert_eq!(
stderr,
format!(
"Error: unable to find a config file for the given path: `{}`\n",
Path::new(&toml_file).display(),
)
);
assert_eq!(stdout, "");
}

#[test]
fn rustfmt_allow_not_a_dir_errors() {
// See also https://github.com/rust-lang/rustfmt/pull/6624
Expand Down
Loading