diff --git a/crates/uv-cache/src/lib.rs b/crates/uv-cache/src/lib.rs index 3c3f8e01e..a91b9cdef 100644 --- a/crates/uv-cache/src/lib.rs +++ b/crates/uv-cache/src/lib.rs @@ -631,7 +631,7 @@ pub enum CacheBucket { /// can put next to the wheels as in the `Wheels` bucket. /// /// The unzipped source distribution is stored in a directory matching the source distribution - /// acrhive name. + /// archive name. /// /// Source distributions are built into zipped wheel files (as PEP 517 specifies) and unzipped /// lazily before installing. So when resolving, we only build the wheel and store the archive diff --git a/crates/uv/src/commands/build_frontend.rs b/crates/uv/src/commands/build_frontend.rs index 7e15bfb3e..b24dfdd9f 100644 --- a/crates/uv/src/commands/build_frontend.rs +++ b/crates/uv/src/commands/build_frontend.rs @@ -11,7 +11,7 @@ use uv_distribution_types::{DependencyMetadata, IndexLocations}; use uv_install_wheel::linker::LinkMode; use uv_auth::store_credentials_from_url; -use uv_cache::Cache; +use uv_cache::{Cache, CacheBucket}; use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder}; use uv_configuration::{ BuildKind, BuildOptions, BuildOutput, Concurrency, ConfigSettings, Constraints, @@ -572,7 +572,7 @@ async fn build_package( let ext = SourceDistExtension::from_path(path.as_path()).map_err(|err| { anyhow::anyhow!("`{}` is not a valid source distribution, as it ends with an unsupported extension. Expected one of: {err}.", path.user_display()) })?; - let temp_dir = tempfile::tempdir_in(&output_dir)?; + let temp_dir = tempfile::tempdir_in(cache.bucket(CacheBucket::SourceDistributions))?; uv_extract::stream::archive(reader, ext, temp_dir.path()).await?; // Extract the top-level directory from the archive. diff --git a/crates/uv/tests/it/build.rs b/crates/uv/tests/it/build.rs index d6fa68292..bb8fe310f 100644 --- a/crates/uv/tests/it/build.rs +++ b/crates/uv/tests/it/build.rs @@ -1,7 +1,10 @@ use crate::common::{uv_snapshot, TestContext}; use anyhow::Result; use assert_fs::prelude::*; +use fs_err::File; +use insta::assert_snapshot; use predicates::prelude::predicate; +use zip::ZipArchive; #[test] fn build() -> Result<()> { @@ -1762,3 +1765,56 @@ fn build_no_build_logs() -> Result<()> { Ok(()) } + +/// Check that we have a working git boundary for builds from source dist to wheel in `dist/`. +#[test] +fn git_boundary_in_dist_build() -> Result<()> { + let context = TestContext::new("3.12"); + + let project = context.temp_dir.child("demo"); + project.child("pyproject.toml").write_str( + r#" + [build-system] + requires = ["hatchling"] + build-backend = "hatchling.build" + + [project] + name = "demo" + version = "0.1.0" + requires-python = ">=3.11" + "#, + )?; + project.child("src/demo/__init__.py").write_str( + r#" + def run(): + print("Running like the wind!") + "#, + )?; + + uv_snapshot!(&context.filters(), context.build().current_dir(project.path()), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Building source distribution... + Building wheel from source distribution... + Successfully built dist/demo-0.1.0.tar.gz and dist/demo-0.1.0-py3-none-any.whl + "###); + + // Check that the source file is included + let reader = File::open(project.join("dist/demo-0.1.0-py3-none-any.whl"))?; + let mut files: Vec<_> = ZipArchive::new(reader)? + .file_names() + .map(ToString::to_string) + .collect(); + files.sort(); + assert_snapshot!(files.join("\n"), @r###" + demo-0.1.0.dist-info/METADATA + demo-0.1.0.dist-info/RECORD + demo-0.1.0.dist-info/WHEEL + demo/__init__.py + "###); + + Ok(()) +}