Set UV to the uv executable path (#11326)

This commit is contained in:
Zanie Blue 2025-02-13 12:44:08 -06:00
parent 553b3a7c34
commit 5765e4bdee
6 changed files with 74 additions and 7 deletions

View file

@ -5,6 +5,17 @@ pub struct EnvVars;
#[attribute_env_vars_metadata]
impl EnvVars {
/// The path to the binary that was used to invoke uv.
///
/// This is propagated to all subprocesses spawned by uv.
///
/// If the executable was invoked through a symbolic link, some platforms will return the path
/// of the symbolic link and other platforms will return the path of the symbolic links target.
///
/// See <https://doc.rust-lang.org/std/env/fn.current_exe.html#security> for security
/// considerations.
pub const UV: &'static str = "UV";
/// Equivalent to the `--offline` command-line argument. If set, uv will disable network access.
pub const UV_OFFLINE: &'static str = "UV_OFFLINE";

View file

@ -7,6 +7,8 @@ use std::process::ExitCode;
use uv::main as uv_main;
#[allow(unsafe_code)]
fn main() -> ExitCode {
uv_main(std::env::args_os())
// SAFETY: This is safe because we are running it early in `main` before spawning any threads.
unsafe { uv_main(std::env::args_os()) }
}

View file

@ -1813,16 +1813,35 @@ async fn run_project(
/// The main entry point for a uv invocation.
///
/// WARNING: This entry point is not recommended for external consumption, the
/// uv binary interface is the official public API. When using this entry
/// point, uv assumes it is running in a process it controls and that the
/// entire process lifetime is managed by uv. Unexpected behavior may be
/// encountered if this entry point is called multiple times in a single process.
pub fn main<I, T>(args: I) -> ExitCode
/// # Usage
///
/// This entry point is not recommended for external consumption, the uv binary interface is the
/// official public API.
///
/// When using this entry point, uv assumes it is running in a process it controls and that the
/// entire process lifetime is managed by uv. Unexpected behavior may be encountered if this entry
/// point is called multiple times in a single process.
///
/// # Safety
///
/// It is only safe to call this routine when it is known that multiple threads are not running.
#[allow(unsafe_code)]
pub unsafe fn main<I, T>(args: I) -> ExitCode
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
// Set the `UV` variable to the current executable so it is implicitly propagated to all child
// processes, e.g., in `uv run`.
if let Ok(current_exe) = std::env::current_exe() {
// SAFETY: The proof obligation must be satisfied by the caller.
unsafe {
// This will become unsafe in Rust 2024
// See https://doc.rust-lang.org/std/env/fn.set_var.html#safety
std::env::set_var(EnvVars::UV, current_exe);
}
}
// `std::env::args` is not `Send` so we parse before passing to our runtime
// https://github.com/rust-lang/rust/pull/48005
let cli = match Cli::try_parse_from(args) {

View file

@ -362,6 +362,12 @@ impl TestContext {
let mut filters = Vec::new();
filters.extend(
Self::path_patterns(get_bin())
.into_iter()
.map(|pattern| (pattern, "[UV]".to_string())),
);
// Exclude `link-mode` on Windows since we set it in the remote test suite
if cfg!(windows) {
filters.push((" --link-mode <LINK_MODE>".to_string(), String::new()));

View file

@ -4350,3 +4350,20 @@ fn detect_infinite_recursion() -> Result<()> {
Ok(())
}
#[test]
fn run_uv_variable() {
let context = TestContext::new("3.12");
// Display the `UV` variable
uv_snapshot!(
context.filters(),
context.run().arg("python").arg("-c").arg("import os; print(os.environ['UV'])"), @r###"
success: true
exit_code: 0
----- stdout -----
[UV]
----- stderr -----
"###);
}