mirror of https://github.com/astral-sh/ruff
Feat: detect changes also in configuration files (#4169)
This commit is contained in:
parent
318653c427
commit
04e8e74499
|
|
@ -43,6 +43,36 @@ impl From<ExitStatus> for ExitCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
enum ChangeKind {
|
||||||
|
Configuration,
|
||||||
|
SourceFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the [`ChangeKind`] based on the list of modified file paths.
|
||||||
|
///
|
||||||
|
/// Returns `None` if no relevant changes were detected.
|
||||||
|
fn change_detected(paths: &[PathBuf]) -> Option<ChangeKind> {
|
||||||
|
// If any `.toml` files were modified, return `ChangeKind::Configuration`. Otherwise, return
|
||||||
|
// `ChangeKind::SourceFile` if any `.py`, `.pyi`, or `.pyw` files were modified.
|
||||||
|
let mut source_file = false;
|
||||||
|
for path in paths {
|
||||||
|
if let Some(suffix) = path.extension() {
|
||||||
|
match suffix.to_str() {
|
||||||
|
Some("toml") => {
|
||||||
|
return Some(ChangeKind::Configuration);
|
||||||
|
}
|
||||||
|
Some("py" | "pyi" | "pyw") => source_file = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if source_file {
|
||||||
|
return Some(ChangeKind::SourceFile);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
Args {
|
Args {
|
||||||
command,
|
command,
|
||||||
|
|
@ -207,30 +237,41 @@ fn check(args: CheckArgs, log_level: LogLevel) -> Result<ExitStatus> {
|
||||||
for file in &cli.files {
|
for file in &cli.files {
|
||||||
watcher.watch(file, RecursiveMode::Recursive)?;
|
watcher.watch(file, RecursiveMode::Recursive)?;
|
||||||
}
|
}
|
||||||
|
if let Some(file) = pyproject_config.path.as_ref() {
|
||||||
|
watcher.watch(file, RecursiveMode::Recursive)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In watch mode, we may need to re-resolve the configuration.
|
||||||
|
// TODO(charlie): Re-compute other derivative values, like the `printer`.
|
||||||
|
let mut pyproject_config = pyproject_config;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match rx.recv() {
|
match rx.recv() {
|
||||||
Ok(event) => {
|
Ok(event) => {
|
||||||
let paths = event?.paths;
|
let Some(change_kind) = change_detected(&event?.paths) else {
|
||||||
let py_changed = paths.iter().any(|path| {
|
continue;
|
||||||
path.extension()
|
};
|
||||||
.map(|ext| ext == "py" || ext == "pyi")
|
|
||||||
.unwrap_or_default()
|
|
||||||
});
|
|
||||||
if py_changed {
|
|
||||||
Printer::clear_screen()?;
|
|
||||||
printer.write_to_user("File change detected...\n");
|
|
||||||
|
|
||||||
let messages = commands::run::run(
|
if matches!(change_kind, ChangeKind::Configuration) {
|
||||||
&cli.files,
|
pyproject_config = resolve::resolve(
|
||||||
&pyproject_config,
|
cli.isolated,
|
||||||
|
cli.config.as_deref(),
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cli.stdin_filename.as_deref(),
|
||||||
noqa.into(),
|
|
||||||
autofix,
|
|
||||||
)?;
|
)?;
|
||||||
printer.write_continuously(&messages)?;
|
|
||||||
}
|
}
|
||||||
|
Printer::clear_screen()?;
|
||||||
|
printer.write_to_user("File change detected...\n");
|
||||||
|
|
||||||
|
let messages = commands::run::run(
|
||||||
|
&cli.files,
|
||||||
|
&pyproject_config,
|
||||||
|
&overrides,
|
||||||
|
cache.into(),
|
||||||
|
noqa.into(),
|
||||||
|
autofix,
|
||||||
|
)?;
|
||||||
|
printer.write_continuously(&messages)?;
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
}
|
}
|
||||||
|
|
@ -311,3 +352,83 @@ fn check(args: CheckArgs, log_level: LogLevel) -> Result<ExitStatus> {
|
||||||
}
|
}
|
||||||
Ok(ExitStatus::Success)
|
Ok(ExitStatus::Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_file_change_detector {
|
||||||
|
use crate::{change_detected, ChangeKind};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn detect_correct_file_change() {
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/pyproject.toml"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("pyproject.toml"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp1/tmp2/tmp3/pyproject.toml"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/ruff.toml"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/.ruff.toml"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::SourceFile),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/rule.py"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::SourceFile),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/rule.pyi"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("pyproject.toml"),
|
||||||
|
PathBuf::from("tmp/rule.py"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ChangeKind::Configuration),
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/rule.py"),
|
||||||
|
PathBuf::from("pyproject.toml"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
None,
|
||||||
|
change_detected(&[
|
||||||
|
PathBuf::from("tmp/rule.js"),
|
||||||
|
PathBuf::from("tmp/bin/ruff.rs"),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue