diff --git a/Cargo.lock b/Cargo.lock index 8c62525df61dc..4e30bcbc77e3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4784,7 +4784,6 @@ name = "uv-distribution" version = "0.0.1" dependencies = [ "anyhow", - "cache-key", "distribution-filename", "distribution-types", "fs-err", diff --git a/crates/install-wheel-rs/Cargo.toml b/crates/install-wheel-rs/Cargo.toml index a52045ba2e959..43feb43590554 100644 --- a/crates/install-wheel-rs/Cargo.toml +++ b/crates/install-wheel-rs/Cargo.toml @@ -2,7 +2,7 @@ name = "install-wheel-rs" version = "0.0.1" publish = false -description = "Takes a wheel and installs it, either in a venv or for monotrail" +description = "Takes a wheel and installs it." keywords = ["wheel", "python"] edition = { workspace = true } diff --git a/crates/install-wheel-rs/Readme.md b/crates/install-wheel-rs/Readme.md deleted file mode 100644 index f339a109b33a4..0000000000000 --- a/crates/install-wheel-rs/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# install-wheel-rs - -Reimplementation of wheel installing in Rust. diff --git a/crates/uv-cache-info/src/cache_info.rs b/crates/uv-cache-info/src/cache_info.rs index c0e92c056c493..544dc05d91798 100644 --- a/crates/uv-cache-info/src/cache_info.rs +++ b/crates/uv-cache-info/src/cache_info.rs @@ -6,15 +6,23 @@ use std::cmp::max; use std::io; use std::path::{Path, PathBuf}; +/// The information used to determine whether a built distribution is up-to-date, based on the +/// timestamps of relevant files, the current commit of a repository, etc. #[derive(Default, Debug, Clone, Hash, PartialEq, Eq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "kebab-case")] #[serde(try_from = "CacheInfoWire")] pub struct CacheInfo { + /// The timestamp of the most recent `ctime` of any relevant files, at the time of the build. + /// The timestamp will typically be the maximum of the `ctime` values of the `pyproject.toml`, + /// `setup.py`, and `setup.cfg` files, if they exist; however, users can provide additional + /// files to timestamp via the `cache-keys` field. timestamp: Option, + /// The commit at which the distribution was built. commit: Option, } impl CacheInfo { + /// Return the [`CacheInfo`] for a given timestamp. pub fn from_timestamp(timestamp: Timestamp) -> Self { Self { timestamp: Some(timestamp), @@ -22,6 +30,7 @@ impl CacheInfo { } } + /// Compute the cache info for a given path, which may be a file or a directory. pub fn from_path(path: &Path) -> io::Result { let metadata = fs_err::metadata(path)?; if metadata.is_file() { @@ -31,6 +40,7 @@ impl CacheInfo { } } + /// Compute the cache info for a given directory. pub fn from_directory(directory: &Path) -> io::Result { let mut commit = None; @@ -103,6 +113,8 @@ impl CacheInfo { Ok(Self { timestamp, commit }) } + /// Compute the cache info for a given file, assumed to be a binary or source distribution + /// represented as (e.g.) a `.whl` or `.tar.gz` archive. pub fn from_file(path: impl AsRef) -> Result { let metadata = fs_err::metadata(path.as_ref())?; let timestamp = Timestamp::from_metadata(&metadata); @@ -126,7 +138,10 @@ struct TimestampCommit { #[derive(Debug, serde::Deserialize)] #[serde(untagged)] enum CacheInfoWire { + /// For backwards-compatibility, enable deserializing [`CacheInfo`] structs that are solely + /// represented by a timestamp. Timestamp(Timestamp), + /// A [`CacheInfo`] struct that includes both a timestamp and a commit. TimestampCommit(TimestampCommit), } diff --git a/crates/uv-cache-info/src/commit_info.rs b/crates/uv-cache-info/src/commit_info.rs index de0b620b8d74c..533b54a6fcf14 100644 --- a/crates/uv-cache-info/src/commit_info.rs +++ b/crates/uv-cache-info/src/commit_info.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -/// The current commit for a repository. +/// The current commit for a repository (i.e., a 40-character hexadecimal string). #[derive(Default, Debug, Clone, Hash, PartialEq, Eq, serde::Deserialize, serde::Serialize)] pub(crate) struct Commit(String); diff --git a/crates/uv-dispatch/src/lib.rs b/crates/uv-dispatch/src/lib.rs index 2b66b9ab45fd5..bbd71ab1dd1f1 100644 --- a/crates/uv-dispatch/src/lib.rs +++ b/crates/uv-dispatch/src/lib.rs @@ -214,7 +214,6 @@ impl<'a> BuildContext for BuildDispatch<'a> { &BuildOptions::default(), self.hasher, self.index_locations, - self.config_settings, self.cache(), venv, &markers, diff --git a/crates/uv-distribution/Cargo.toml b/crates/uv-distribution/Cargo.toml index 26d445d8a211b..4b798c0253796 100644 --- a/crates/uv-distribution/Cargo.toml +++ b/crates/uv-distribution/Cargo.toml @@ -13,7 +13,6 @@ license = { workspace = true } workspace = true [dependencies] -cache-key = { workspace = true } distribution-filename = { workspace = true } distribution-types = { workspace = true } install-wheel-rs = { workspace = true } diff --git a/crates/uv-distribution/src/index/built_wheel_index.rs b/crates/uv-distribution/src/index/built_wheel_index.rs index 1f5caf94ce4bf..a7e83f7ecc7f8 100644 --- a/crates/uv-distribution/src/index/built_wheel_index.rs +++ b/crates/uv-distribution/src/index/built_wheel_index.rs @@ -7,7 +7,6 @@ use distribution_types::{ use platform_tags::Tags; use uv_cache::{Cache, CacheBucket, CacheShard, WheelCache}; use uv_cache_info::CacheInfo; -use uv_configuration::ConfigSettings; use uv_fs::symlinks; use uv_types::HashStrategy; @@ -17,22 +16,15 @@ pub struct BuiltWheelIndex<'a> { cache: &'a Cache, tags: &'a Tags, hasher: &'a HashStrategy, - build_configuration: &'a ConfigSettings, } impl<'a> BuiltWheelIndex<'a> { /// Initialize an index of built distributions. - pub fn new( - cache: &'a Cache, - tags: &'a Tags, - hasher: &'a HashStrategy, - build_configuration: &'a ConfigSettings, - ) -> Self { + pub fn new(cache: &'a Cache, tags: &'a Tags, hasher: &'a HashStrategy) -> Self { Self { cache, tags, hasher, - build_configuration, } } @@ -61,13 +53,6 @@ impl<'a> BuiltWheelIndex<'a> { let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let cache_shard = if self.build_configuration.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(self.build_configuration)) - }; - Ok(self.find(&cache_shard)) } /// Return the most compatible [`CachedWheel`] for a given source distribution at a local path. @@ -98,13 +83,6 @@ impl<'a> BuiltWheelIndex<'a> { let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let cache_shard = if self.build_configuration.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(self.build_configuration)) - }; - Ok(self .find(&cache_shard) .map(|wheel| wheel.with_cache_info(cache_info))) @@ -147,13 +125,6 @@ impl<'a> BuiltWheelIndex<'a> { let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let cache_shard = if self.build_configuration.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(self.build_configuration)) - }; - Ok(self .find(&cache_shard) .map(|wheel| wheel.with_cache_info(cache_info))) @@ -173,13 +144,6 @@ impl<'a> BuiltWheelIndex<'a> { WheelCache::Git(&source_dist.url, &git_sha.to_short_string()).root(), ); - // If there are build settings, we need to scope to a cache shard. - let cache_shard = if self.build_configuration.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(self.build_configuration)) - }; - self.find(&cache_shard) } diff --git a/crates/uv-distribution/src/source/mod.rs b/crates/uv-distribution/src/source/mod.rs index cf908f2963aca..483e4619b5873 100644 --- a/crates/uv-distribution/src/source/mod.rs +++ b/crates/uv-distribution/src/source/mod.rs @@ -426,14 +426,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { // freshness, since entries have to be fresher than the revision itself. let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // If the cache contains a compatible wheel, return it. if let Some(built_wheel) = BuiltWheelMetadata::find_in_cache(tags, &cache_shard) { return Ok(built_wheel.with_hashes(revision.into_hashes())); @@ -527,14 +519,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { }); } - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // Otherwise, we either need to build the metadata. // If the backend supports `prepare_metadata_for_build_wheel`, use it. if let Some(metadata) = self @@ -687,14 +671,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { // freshness, since entries have to be fresher than the revision itself. let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // If the cache contains a compatible wheel, return it. if let Some(built_wheel) = BuiltWheelMetadata::find_in_cache(tags, &cache_shard) { return Ok(built_wheel); @@ -805,14 +781,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { }); } - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // Otherwise, we need to build a wheel. let task = self .reporter @@ -929,14 +897,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { // freshness, since entries have to be fresher than the revision itself. let cache_shard = cache_shard.shard(revision.id()); - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // If the cache contains a compatible wheel, return it. if let Some(built_wheel) = BuiltWheelMetadata::find_in_cache(tags, &cache_shard) { return Ok(built_wheel); @@ -1060,14 +1020,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { )); } - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // Otherwise, we need to build a wheel. let task = self .reporter @@ -1179,14 +1131,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { let _lock = lock_shard(&cache_shard).await?; - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // If the cache contains a compatible wheel, return it. if let Some(built_wheel) = BuiltWheelMetadata::find_in_cache(tags, &cache_shard) { return Ok(built_wheel); @@ -1313,14 +1257,6 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { )); } - // If there are build settings, we need to scope to a cache shard. - let config_settings = self.build_context.config_settings(); - let cache_shard = if config_settings.is_empty() { - cache_shard - } else { - cache_shard.shard(cache_key::cache_digest(config_settings)) - }; - // Otherwise, we need to build a wheel. let task = self .reporter diff --git a/crates/uv-installer/src/plan.rs b/crates/uv-installer/src/plan.rs index 26bcb051d4c6b..2c5c73d38cd43 100644 --- a/crates/uv-installer/src/plan.rs +++ b/crates/uv-installer/src/plan.rs @@ -15,7 +15,7 @@ use platform_tags::Tags; use pypi_types::{Requirement, RequirementSource, ResolverMarkerEnvironment}; use uv_cache::{Cache, CacheBucket, WheelCache}; use uv_cache_info::{CacheInfo, Timestamp}; -use uv_configuration::{BuildOptions, ConfigSettings, Reinstall}; +use uv_configuration::{BuildOptions, Reinstall}; use uv_distribution::{ BuiltWheelIndex, HttpArchivePointer, LocalArchivePointer, RegistryWheelIndex, }; @@ -57,7 +57,6 @@ impl<'a> Planner<'a> { build_options: &BuildOptions, hasher: &HashStrategy, index_locations: &IndexLocations, - config_settings: &ConfigSettings, cache: &Cache, venv: &PythonEnvironment, markers: &ResolverMarkerEnvironment, @@ -65,7 +64,7 @@ impl<'a> Planner<'a> { ) -> Result { // Index all the already-downloaded wheels in the cache. let mut registry_index = RegistryWheelIndex::new(cache, tags, index_locations, hasher); - let built_index = BuiltWheelIndex::new(cache, tags, hasher, config_settings); + let built_index = BuiltWheelIndex::new(cache, tags, hasher); let mut cached = vec![]; let mut remote = vec![]; diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index 4441c2ecc0249..7223c671e0d2d 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -407,7 +407,6 @@ pub(crate) async fn pip_install( link_mode, compile, &index_locations, - config_settings, &hasher, &markers, &tags, diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index 3663a8fe57a8f..9801290c4215b 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -21,8 +21,7 @@ use pypi_types::ResolverMarkerEnvironment; use uv_cache::Cache; use uv_client::{BaseClientBuilder, RegistryClient}; use uv_configuration::{ - BuildOptions, Concurrency, ConfigSettings, Constraints, ExtrasSpecification, Overrides, - Reinstall, Upgrade, + BuildOptions, Concurrency, Constraints, ExtrasSpecification, Overrides, Reinstall, Upgrade, }; use uv_dispatch::BuildDispatch; use uv_distribution::DistributionDatabase; @@ -350,7 +349,6 @@ pub(crate) async fn install( link_mode: LinkMode, compile: bool, index_urls: &IndexLocations, - config_settings: &ConfigSettings, hasher: &HashStrategy, markers: &ResolverMarkerEnvironment, tags: &Tags, @@ -378,7 +376,6 @@ pub(crate) async fn install( build_options, hasher, index_urls, - config_settings, cache, venv, markers, diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index 4e1e102c9698f..383f5a880a872 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -359,7 +359,6 @@ pub(crate) async fn pip_sync( link_mode, compile, &index_locations, - config_settings, &hasher, &markers, &tags, diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index 20febff9c3c7c..8f5ed2dc5200e 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -807,7 +807,6 @@ pub(crate) async fn sync_environment( link_mode, compile_bytecode, index_locations, - config_setting, &hasher, &markers, tags, @@ -1040,7 +1039,6 @@ pub(crate) async fn update_environment( *link_mode, *compile_bytecode, index_locations, - config_setting, &hasher, &markers, tags, diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index c177e55543aac..bedd907337021 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -304,7 +304,6 @@ pub(super) async fn do_sync( link_mode, compile_bytecode, index_locations, - config_setting, &hasher, &markers, tags, diff --git a/crates/uv/tests/pip_install.rs b/crates/uv/tests/pip_install.rs index 511461427bab6..de29a2923d015 100644 --- a/crates/uv/tests/pip_install.rs +++ b/crates/uv/tests/pip_install.rs @@ -2764,37 +2764,9 @@ fn config_settings() { .join("__editable___setuptools_editable_0_1_0_finder.py"); assert!(finder.exists()); - // Reinstalling with `--editable_mode=compat` should be a no-op; changes in build configuration - // don't invalidate the environment. - uv_snapshot!(context.filters(), context.pip_install() - .arg("-e") - .arg(context.workspace_root.join("scripts/packages/setuptools_editable")) - .arg("-C") - .arg("editable_mode=compat") - , @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - Audited 1 package in [TIME] - "### - ); - - // Uninstall the package. - uv_snapshot!(context.filters(), context.pip_uninstall() - .arg("setuptools-editable"), @r###" - success: true - exit_code: 0 - ----- stdout ----- - - ----- stderr ----- - Uninstalled 1 package in [TIME] - - setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable) - "###); + // Install the editable package with `--editable_mode=compat`. + let context = TestContext::new("3.12"); - // Install the editable package with `--editable_mode=compat`. We should ignore the cached - // build configuration and rebuild. uv_snapshot!(context.filters(), context.pip_install() .arg("-e") .arg(context.workspace_root.join("scripts/packages/setuptools_editable")) @@ -2807,8 +2779,9 @@ fn config_settings() { ----- stderr ----- Resolved 2 packages in [TIME] - Prepared 1 package in [TIME] - Installed 1 package in [TIME] + Prepared 2 packages in [TIME] + Installed 2 packages in [TIME] + + iniconfig==2.0.0 + setuptools-editable==0.1.0 (from file://[WORKSPACE]/scripts/packages/setuptools_editable) "### ); @@ -2953,7 +2926,7 @@ requires-python = ">=3.8" "### ); - // Re-installing should be a no-op. + // Installing again should be a no-op. uv_snapshot!(context.filters(), context.pip_install() .arg("--editable") .arg(editable_dir.path()), @r###" @@ -3095,7 +3068,7 @@ requires-python = ">=3.8" "### ); - // Re-installing should be a no-op. + // Installing again should be a no-op. uv_snapshot!(context.filters(), context.pip_install() .arg("example @ .") .current_dir(editable_dir.path()), @r###" @@ -3186,7 +3159,7 @@ fn invalidate_path_on_cache_key() -> Result<()> { "### ); - // Re-installing should be a no-op. + // Installing again should be a no-op. uv_snapshot!(context.filters(), context.pip_install() .arg("example @ .") .current_dir(editable_dir.path()), @r###" @@ -3296,7 +3269,7 @@ fn invalidate_path_on_commit() -> Result<()> { "### ); - // Re-installing should be a no-op. + // Installing again should be a no-op. uv_snapshot!(context.filters(), context.pip_install() .arg("example @ .") .current_dir(editable_dir.path()), @r###" diff --git a/crates/uv/tests/pip_sync.rs b/crates/uv/tests/pip_sync.rs index eceb189438557..791b0f2b1cf1a 100644 --- a/crates/uv/tests/pip_sync.rs +++ b/crates/uv/tests/pip_sync.rs @@ -3215,7 +3215,7 @@ requires-python = ">=3.8" "### ); - // Re-installing should be a no-op. + // Installing again should be a no-op. uv_snapshot!(context.filters(), context.pip_sync() .arg("requirements.in"), @r###" success: true