Skip to content

Commit

Permalink
Reflect exit code in uv tool run and uv run
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 4, 2024
1 parent 3d75df6 commit 427ce11
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
4 changes: 4 additions & 0 deletions crates/uv/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub(crate) enum ExitStatus {

/// The command failed with an unexpected error.
Error,

/// The command's exit status is propagated from an external command.
External(u8),
}

impl From<ExitStatus> for ExitCode {
Expand All @@ -88,6 +91,7 @@ impl From<ExitStatus> for ExitCode {
ExitStatus::Success => Self::from(0),
ExitStatus::Failure => Self::from(1),
ExitStatus::Error => Self::from(2),
ExitStatus::External(code) => Self::from(code),
}
}
}
Expand Down
16 changes: 13 additions & 3 deletions crates/uv/src/commands/project/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,10 +679,20 @@ pub(crate) async fn run(
let status = handle.wait().await.context("Child process disappeared")?;

// Exit based on the result of the command
// TODO(zanieb): Do we want to exit with the code of the child process? Probably.
if status.success() {
Ok(ExitStatus::Success)
if let Some(code) = status.code() {
debug!("Command exited with code: {code}");
if let Ok(code) = u8::try_from(code) {
Ok(ExitStatus::External(code))
} else {
#[allow(clippy::exit)]
std::process::exit(code);
}
} else {
#[cfg(unix)]
{
use std::os::unix::process::ExitStatusExt;
debug!("Command exited with signal: {:?}", status.signal());
}
Ok(ExitStatus::Failure)
}
}
Expand Down
16 changes: 13 additions & 3 deletions crates/uv/src/commands/tool/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,20 @@ pub(crate) async fn run(
let status = handle.wait().await.context("Child process disappeared")?;

// Exit based on the result of the command
// TODO(zanieb): Do we want to exit with the code of the child process? Probably.
if status.success() {
Ok(ExitStatus::Success)
if let Some(code) = status.code() {
debug!("Command exited with code: {code}");
if let Ok(code) = u8::try_from(code) {
Ok(ExitStatus::External(code))
} else {
#[allow(clippy::exit)]
std::process::exit(code);
}
} else {
#[cfg(unix)]
{
use std::os::unix::process::ExitStatusExt;
debug!("Command exited with signal: {:?}", status.signal());
}
Ok(ExitStatus::Failure)
}
}
Expand Down
19 changes: 19 additions & 0 deletions crates/uv/tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,3 +1774,22 @@ fn run_compiled_python_file() -> Result<()> {

Ok(())
}

#[test]
fn run_exit_code() -> Result<()> {
let context = TestContext::new("3.12");

let test_script = context.temp_dir.child("script.py");
test_script.write_str(indoc! { r#"
# /// script
# requires-python = ">=3.11"
# ///
exit(42)
"#
})?;

context.run().arg("script.py").assert().code(42);

Ok(())
}

0 comments on commit 427ce11

Please sign in to comment.