diff --git a/Cargo.lock b/Cargo.lock index fa39ba32d2..8869d8bef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -754,6 +754,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "eyre" version = "0.6.12" @@ -2493,7 +2504,7 @@ version = "0.0.0" dependencies = [ "anyhow", "colored", - "dirs 5.0.1", + "etcetera", "glob", "globset", "ignore", diff --git a/Cargo.toml b/Cargo.toml index c617d5d69e..645ee958a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,9 +58,9 @@ countme = { version = "3.0.1" } criterion = { version = "0.5.1", default-features = false } crossbeam = { version = "0.8.4" } dashmap = { version = "5.5.3" } -dirs = { version = "5.0.0" } drop_bomb = { version = "0.1.5" } env_logger = { version = "0.11.0" } +etcetera = { version = "0.8.0" } fern = { version = "0.6.1" } filetime = { version = "0.2.23" } glob = { version = "0.3.1" } diff --git a/crates/ruff_workspace/Cargo.toml b/crates/ruff_workspace/Cargo.toml index 25c5fbaa84..20a81205c5 100644 --- a/crates/ruff_workspace/Cargo.toml +++ b/crates/ruff_workspace/Cargo.toml @@ -23,7 +23,6 @@ ruff_macros = { workspace = true } anyhow = { workspace = true } colored = { workspace = true } -dirs = { workspace = true } ignore = { workspace = true } is-macro = { workspace = true } itertools = { workspace = true } @@ -42,6 +41,9 @@ shellexpand = { workspace = true } strum = { workspace = true } toml = { workspace = true } +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +etcetera = { workspace = true } + [dev-dependencies] # Enable test rules during development ruff_linter = { workspace = true, features = ["clap", "test-rules"] } diff --git a/crates/ruff_workspace/src/pyproject.rs b/crates/ruff_workspace/src/pyproject.rs index 75a6d13243..6230672814 100644 --- a/crates/ruff_workspace/src/pyproject.rs +++ b/crates/ruff_workspace/src/pyproject.rs @@ -98,31 +98,44 @@ pub fn find_settings_toml>(path: P) -> Result> { /// Find the path to the user-specific `pyproject.toml` or `ruff.toml`, if it /// exists. +#[cfg(not(target_arch = "wasm32"))] pub fn find_user_settings_toml() -> Option { - // Search for a user-specific `.ruff.toml`. - let mut path = dirs::config_dir()?; - path.push("ruff"); - path.push(".ruff.toml"); - if path.is_file() { - return Some(path); + use etcetera::BaseStrategy; + use ruff_linter::warn_user_once; + + let strategy = etcetera::base_strategy::choose_base_strategy().ok()?; + let config_dir = strategy.config_dir().join("ruff"); + + // Search for a user-specific `.ruff.toml`, then a `ruff.toml`, then a `pyproject.toml`. + for filename in [".ruff.toml", "ruff.toml", "pyproject.toml"] { + let path = config_dir.join(filename); + if path.is_file() { + return Some(path); + } } - // Search for a user-specific `ruff.toml`. - let mut path = dirs::config_dir()?; - path.push("ruff"); - path.push("ruff.toml"); - if path.is_file() { - return Some(path); + // On macOS, we used to support reading from `/Users/Alice/Library/Application Support`. + if cfg!(target_os = "macos") { + let strategy = etcetera::base_strategy::Apple::new().ok()?; + let deprecated_config_dir = strategy.data_dir().join("ruff"); + + for file in [".ruff.toml", "ruff.toml", "pyproject.toml"] { + let path = deprecated_config_dir.join(file); + if path.is_file() { + warn_user_once!( + "Reading configuration from `~/Library/Application Support` is deprecated. Please move your configuration to `{}/{file}`.", + config_dir.display(), + ); + return Some(path); + } + } } - // Search for a user-specific `pyproject.toml`. - let mut path = dirs::config_dir()?; - path.push("ruff"); - path.push("pyproject.toml"); - if path.is_file() { - return Some(path); - } + None +} +#[cfg(target_arch = "wasm32")] +pub fn find_user_settings_toml() -> Option { None } diff --git a/docs/faq.md b/docs/faq.md index ed8475f2f5..b287b21c21 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -612,16 +612,20 @@ Ruff doesn't currently support INI files, like `setup.cfg` or `tox.ini`. ## How can I change Ruff's default configuration? -When no configuration file is found, Ruff will look for a user-specific `pyproject.toml` or -`ruff.toml` file as a last resort. This behavior is similar to Flake8's `~/.config/flake8`. +When no configuration file is found, Ruff will look for a user-specific `ruff.toml` file as a +last resort. This behavior is similar to Flake8's `~/.config/flake8`. -On macOS, Ruff expects that file to be located at `/Users/Alice/Library/Application Support/ruff/ruff.toml`. +On macOS and Linux, Ruff expects that file to be located at `~/.config/ruff/ruff.toml`, +and respects the `XDG_CONFIG_HOME` specification. -On Linux, Ruff expects that file to be located at `/home/alice/.config/ruff/ruff.toml`. +On Windows, Ruff expects that file to be located at `~\AppData\Roaming\ruff\ruff.toml`. -On Windows, Ruff expects that file to be located at `C:\Users\Alice\AppData\Roaming\ruff\ruff.toml`. +!!! note + Prior to `v0.5.0`, Ruff would read user-specific configuration from + `~/Library/Application Support/ruff/ruff.toml` on macOS. While Ruff will still respect + such configuration files, the use of `~/Library/ Application Support` is considered deprecated. -For more, see the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate. +For more, see the [`etcetera`](https://crates.io/crates/etcetera) crate. ## Ruff tried to fix something — but it broke my code. What's going on?