[`ruff`] Handle argfile expansion errors gracefully (#20691)

<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Fixes #20655

- Guard `argfile::expand_args_from` with contextual error handling so
missing @file arguments surface a friendly failure instead of panicking.
- Extract existing stderr reporting into `report_error` for reuse on
both CLI parsing failures and runtime errors.

## Test Plan

<!-- How was it tested? -->

Add a regression test to integration_test.rs.

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This commit is contained in:
Takayuki Maeda 2025-10-03 22:36:07 +09:00 committed by GitHub
parent 542f080035
commit 7d7237c660
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 29 deletions

View File

@ -1,6 +1,7 @@
use std::io::Write;
use std::process::ExitCode;
use anyhow::Context;
use clap::Parser;
use colored::Colorize;
@ -39,13 +40,22 @@ pub fn main() -> ExitCode {
}
let args = wild::args_os();
let args = argfile::expand_args_from(args, argfile::parse_fromfile, argfile::PREFIX).unwrap();
let args = match argfile::expand_args_from(args, argfile::parse_fromfile, argfile::PREFIX)
.context("Failed to read CLI arguments from files")
{
Ok(args) => args,
Err(err) => return report_error(&err),
};
let args = Args::parse_from(args);
match run(args) {
Ok(code) => code.into(),
Err(err) => {
Err(err) => report_error(&err),
}
}
fn report_error(err: &anyhow::Error) -> ExitCode {
{
// Exit "gracefully" on broken pipe errors.
//
@ -72,6 +82,4 @@ pub fn main() -> ExitCode {
}
}
ExitStatus::Error.into()
}
}
}

View File

@ -1688,6 +1688,27 @@ fn check_input_from_argfile() -> Result<()> {
Ok(())
}
#[test]
// Regression test for https://github.com/astral-sh/ruff/issues/20655
fn missing_argfile_reports_error() {
let mut cmd = RuffCheck::default().filename("@!.txt").build();
insta::with_settings!({filters => vec![
("The system cannot find the file specified.", "No such file or directory")
]}, {
assert_cmd_snapshot!(cmd, @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
ruff failed
Cause: Failed to read CLI arguments from files
Cause: failed to open file `!.txt`
Cause: No such file or directory (os error 2)
");
});
}
#[test]
fn check_hints_hidden_unsafe_fixes() {
let mut cmd = RuffCheck::default()