From 2dde053fa80a408d20badd8d5dea4ef485d8106d Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Sat, 3 Aug 2024 12:51:21 -0400 Subject: [PATCH] move all UV logic to build time --- Cargo.toml | 2 +- build.rs | 77 +++++++++++++++++++++++++++++++-------------- src/app.rs | 30 +++--------------- src/distribution.rs | 22 ++----------- 4 files changed, 62 insertions(+), 69 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 438db87..2ea7842 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,8 +81,8 @@ passthrough = [ "PYAPP_SELF_COMMAND", "PYAPP_SKIP_INSTALL", "PYAPP_UPGRADE_VIRTUALENV", - "PYAPP_UV_CUSTOM_SOURCE", "PYAPP_UV_ENABLED", "PYAPP_UV_ONLY_BOOTSTRAP", + "PYAPP_UV_SOURCE", "PYAPP_UV_VERSION", ] diff --git a/build.rs b/build.rs index ab868b8..0d249df 100644 --- a/build.rs +++ b/build.rs @@ -239,6 +239,19 @@ fn check_environment_variable(name: &str) -> String { value } +fn filename_from_url(url: &str) -> String { + let parsed = + reqwest::Url::parse(url).unwrap_or_else(|_| panic!("unable to parse URL: {}", &url)); + + if let Some(segments) = parsed.path_segments() { + if let Some(segment) = segments.last() { + return segment.into(); + } + } + + panic!("unable to determine artifact name from URL: {}", &url); +} + fn is_enabled(name: &str) -> bool { ["true", "1"].contains(&env::var(name).unwrap_or_default().as_str()) } @@ -944,32 +957,51 @@ fn set_uv_only_bootstrap() { } } -fn set_uv_custom_source() { - let variable = "PYAPP_UV_CUSTOM_SOURCE"; - set_runtime_variable(variable, env::var(variable).unwrap_or_default()); -} +fn set_uv_source() { + let source_variable = "PYAPP_UV_SOURCE"; + let mut source = env::var(source_variable).unwrap_or_default(); -fn set_uv_version() { - let variable = "PYAPP_UV_VERSION"; - let version = env::var(variable).unwrap_or("any".to_string()); - set_runtime_variable(variable, version); + if !source.is_empty() { + set_runtime_variable("PYAPP__UV_ARTIFACT_NAME", filename_from_url(&source)); - let artifact_name = if !is_enabled("PYAPP_UV_ENABLED") { - "".to_string() - } else if env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { - // Force MinGW-w64 to use msvc - if env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default() == "gnu" { + let mut hasher = PortableHash::default(); + source.hash(&mut hasher); + set_runtime_variable("PYAPP__UV_VERSION", hasher.finish()); + } else { + let version_variable = "PYAPP_UV_VERSION"; + let version = env::var(version_variable).unwrap_or("any".to_string()); + + let artifact_name = if !is_enabled("PYAPP_UV_ENABLED") { + "".to_string() + } else if env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { + // Force MinGW-w64 to use msvc + if env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default() == "gnu" { + format!( + "uv-{}-pc-windows-msvc.zip", + env::var("CARGO_CFG_TARGET_ARCH").unwrap() + ) + } else { + format!("uv-{}.zip", env::var("TARGET").unwrap()) + } + } else { + format!("uv-{}.tar.gz", env::var("TARGET").unwrap()) + }; + + source = if version == "any" { format!( - "uv-{}-pc-windows-msvc.zip", - env::var("CARGO_CFG_TARGET_ARCH").unwrap() + "https://github.com/astral-sh/uv/releases/latest/download/{}", + &artifact_name, ) } else { - format!("uv-{}.zip", env::var("TARGET").unwrap()) - } - } else { - format!("uv-{}.tar.gz", env::var("TARGET").unwrap()) - }; - set_runtime_variable("PYAPP__UV_ARTIFACT_NAME", artifact_name); + format!( + "https://github.com/astral-sh/uv/releases/download/{}/{}", + &version, &artifact_name, + ) + }; + set_runtime_variable("PYAPP__UV_ARTIFACT_NAME", artifact_name); + set_runtime_variable("PYAPP__UV_VERSION", &version); + } + set_runtime_variable(source_variable, &source); } fn set_skip_install() { @@ -1097,8 +1129,7 @@ fn main() { set_pip_allow_config(); set_uv_enabled(); set_uv_only_bootstrap(); - set_uv_custom_source(); - set_uv_version(); + set_uv_source(); set_allow_updates(); set_indicator(); set_self_command(); diff --git a/src/app.rs b/src/app.rs index 24688fb..a7dde3d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -7,7 +7,6 @@ use anyhow::{Context, Result}; use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _}; use directories::ProjectDirs; use once_cell::sync::OnceCell; -use reqwest::Url; static PLATFORM_DIRS: OnceCell = OnceCell::new(); static INSTALLATION_DIRECTORY: OnceCell = OnceCell::new(); @@ -196,7 +195,11 @@ pub fn uv_only_bootstrap() -> bool { } pub fn uv_version() -> String { - env!("PYAPP_UV_VERSION").into() + env!("PYAPP__UV_VERSION").into() +} + +pub fn uv_source() -> String { + env!("PYAPP_UV_SOURCE").into() } pub fn uv_artifact_name() -> String { @@ -207,29 +210,6 @@ pub fn uv_as_installer() -> bool { uv_enabled() && !uv_only_bootstrap() } -pub fn uv_custom_source() -> String { - env!("PYAPP_UV_CUSTOM_SOURCE").into() -} - -pub fn uv_custom_source_artifact_name() -> String { - let custom_source = uv_custom_source(); - - let parsed = - Url::parse(&custom_source).expect(&format!("unable to parse url: {}", &custom_source)); - - // Try to find artifact name from URL path - if let Some(segments) = parsed.path_segments() { - if let Some(segment) = segments.last() { - return segment.into(); - } - } - - panic!( - "unable to determine artifact name from url: {}", - &custom_source - ); -} - pub fn is_gui() -> bool { env!("PYAPP_IS_GUI") == "1" } diff --git a/src/distribution.rs b/src/distribution.rs index 5543d58..2ea840a 100644 --- a/src/distribution.rs +++ b/src/distribution.rs @@ -488,31 +488,13 @@ fn ensure_uv_available() -> Result<()> { .with_context(|| format!("unable to create UV cache {}", &managed_uv_cache.display()))?; let dir = tempdir().with_context(|| "unable to create temporary directory")?; - - let artifact_name: String = if app::uv_custom_source().is_empty() { - app::uv_artifact_name() - } else { - app::uv_custom_source_artifact_name() - }; + let artifact_name: String = app::uv_artifact_name(); let temp_path = dir.path().join(&artifact_name); let mut f = fs::File::create(&temp_path) .with_context(|| format!("unable to create temporary file: {}", &temp_path.display()))?; - let url = if !app::uv_custom_source().is_empty() { - app::uv_custom_source() - } else if uv_version == "any" { - format!( - "https://github.com/astral-sh/uv/releases/latest/download/{}", - &artifact_name, - ) - } else { - format!( - "https://github.com/astral-sh/uv/releases/download/{}/{}", - &uv_version, &artifact_name, - ) - }; - network::download(&url, &mut f, "UV")?; + network::download(&app::uv_source(), &mut f, "UV")?; if artifact_name.ends_with(".zip") { compression::unpack_zip(temp_path, dir.path(), "Unpacking UV".to_string())