From d462d6651c2873b420a5b95aa7f666e3816dbf7c Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 3 Mar 2024 19:04:24 -0500 Subject: [PATCH] Move shell expansion into --config lookup --- crates/ruff/src/args.rs | 13 ++++++----- crates/ruff/src/resolve.rs | 13 ++++------- crates/ruff/tests/lint.rs | 44 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/crates/ruff/src/args.rs b/crates/ruff/src/args.rs index 329c5557dac506..6c3e0f0561da52 100644 --- a/crates/ruff/src/args.rs +++ b/crates/ruff/src/args.rs @@ -806,15 +806,18 @@ impl TypedValueParser for ConfigArgumentParser { arg: Option<&clap::Arg>, value: &std::ffi::OsStr, ) -> Result { - let path_to_config_file = PathBuf::from(value); - if path_to_config_file.exists() { - return Ok(SingleConfigArgument::FilePath(path_to_config_file)); - } - let value = value .to_str() .ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?; + if let Ok(path_to_config_file) = + shellexpand::full(value).map(|config| PathBuf::from(config.as_ref())) + { + if path_to_config_file.is_file() { + return Ok(SingleConfigArgument::FilePath(path_to_config_file)); + } + } + let config_parse_error = match toml::Table::from_str(value) { Ok(table) => match table.try_into::() { Ok(option) => { diff --git a/crates/ruff/src/resolve.rs b/crates/ruff/src/resolve.rs index a645583d08a2d5..f74efa4317a539 100644 --- a/crates/ruff/src/resolve.rs +++ b/crates/ruff/src/resolve.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use anyhow::Result; use log::debug; @@ -35,13 +35,8 @@ pub fn resolve( // Second priority: the user specified a `pyproject.toml` file. Use that // `pyproject.toml` for _all_ configuration, and resolve paths relative to the // current working directory. (This matches ESLint's behavior.) - if let Some(pyproject) = config_arguments - .config_file() - .map(|config| config.display().to_string()) - .map(|config| shellexpand::full(&config).map(|config| PathBuf::from(config.as_ref()))) - .transpose()? - { - let settings = resolve_root_settings(&pyproject, Relativity::Cwd, config_arguments)?; + if let Some(pyproject) = config_arguments.config_file() { + let settings = resolve_root_settings(pyproject, Relativity::Cwd, config_arguments)?; debug!( "Using user-specified configuration file at: {}", pyproject.display() @@ -49,7 +44,7 @@ pub fn resolve( return Ok(PyprojectConfig::new( PyprojectDiscoveryStrategy::Fixed, settings, - Some(pyproject), + Some(pyproject.to_path_buf()), )); } diff --git a/crates/ruff/tests/lint.rs b/crates/ruff/tests/lint.rs index 900fc5382f24b6..23aa96ea4cca53 100644 --- a/crates/ruff/tests/lint.rs +++ b/crates/ruff/tests/lint.rs @@ -1126,3 +1126,47 @@ import os Ok(()) } + +/// Expand environment variables in `--config` paths provided via the CLI. +#[test] +fn config_expand() -> Result<()> { + let tempdir = TempDir::new()?; + let ruff_toml = tempdir.path().join("ruff.toml"); + fs::write( + ruff_toml, + r#" +[lint] +select = ["F"] +ignore = ["F841"] +"#, + )?; + + insta::with_settings!({ + filters => vec![(tempdir_filter(&tempdir).as_str(), "[TMP]/")] + }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .args(STDIN_BASE_OPTIONS) + .arg("--config") + .arg("${NAME}.toml") + .env("NAME", "ruff") + .arg("-") + .current_dir(tempdir.path()) + .pass_stdin(r#" +import os + +def func(): + x = 1 +"#), @r###" + success: false + exit_code: 1 + ----- stdout ----- + -:2:8: F401 [*] `os` imported but unused + Found 1 error. + [*] 1 fixable with the `--fix` option. + + ----- stderr ----- + "###); + }); + + Ok(()) +}