Skip to content

Commit

Permalink
Read cached registry distributions when --config-settings are prese…
Browse files Browse the repository at this point in the history
…nt (#10578)

## Summary

Closes #10577.
  • Loading branch information
charliermarsh authored Jan 13, 2025
1 parent 53d3d5e commit b6aa40b
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 6 deletions.
21 changes: 18 additions & 3 deletions crates/uv-distribution/src/index/registry_wheel_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::collections::hash_map::Entry;
use rustc_hash::{FxHashMap, FxHashSet};

use uv_cache::{Cache, CacheBucket, WheelCache};
use uv_cache_key::cache_digest;
use uv_configuration::ConfigSettings;
use uv_distribution_types::{CachedRegistryDist, Hashed, Index, IndexLocations, IndexUrl};
use uv_fs::{directories, files, symlinks};
use uv_normalize::PackageName;
Expand Down Expand Up @@ -31,6 +33,7 @@ pub struct RegistryWheelIndex<'a> {
index_locations: &'a IndexLocations,
hasher: &'a HashStrategy,
index: FxHashMap<&'a PackageName, Vec<IndexEntry<'a>>>,
build_configuration: &'a ConfigSettings,
}

impl<'a> RegistryWheelIndex<'a> {
Expand All @@ -40,12 +43,14 @@ impl<'a> RegistryWheelIndex<'a> {
tags: &'a Tags,
index_locations: &'a IndexLocations,
hasher: &'a HashStrategy,
build_configuration: &'a ConfigSettings,
) -> Self {
Self {
cache,
tags,
index_locations,
hasher,
build_configuration,
index: FxHashMap::default(),
}
}
Expand All @@ -67,6 +72,7 @@ impl<'a> RegistryWheelIndex<'a> {
self.tags,
self.index_locations,
self.hasher,
self.build_configuration,
)),
};
versions
Expand All @@ -79,6 +85,7 @@ impl<'a> RegistryWheelIndex<'a> {
tags: &Tags,
index_locations: &'index IndexLocations,
hasher: &HashStrategy,
build_configuration: &ConfigSettings,
) -> Vec<IndexEntry<'index>> {
let mut entries = vec![];

Expand Down Expand Up @@ -162,9 +169,8 @@ impl<'a> RegistryWheelIndex<'a> {
WheelCache::Index(index.url()).wheel_dir(package.to_string()),
);

// For registry wheels, the cache structure is: `<index>/<package-name>/<version>/`.
// For registry source distributions, the cache structure is: `<index>/<package-name>/<version>/`.
for shard in directories(&cache_shard) {
// Read the existing metadata from the cache, if it exists.
let cache_shard = cache_shard.shard(shard);

// Read the revision from the cache.
Expand All @@ -190,7 +196,16 @@ impl<'a> RegistryWheelIndex<'a> {
};

if let Some(revision) = revision {
for wheel_dir in symlinks(cache_shard.join(revision.id())) {
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 build_configuration.is_empty() {
cache_shard
} else {
cache_shard.shard(cache_digest(build_configuration))
};

for wheel_dir in symlinks(cache_shard) {
if let Some(wheel) = CachedWheel::from_built_source(wheel_dir) {
if wheel.filename.compatibility(tags).is_compatible() {
// Enforce hash-checking based on the source distribution.
Expand Down
5 changes: 3 additions & 2 deletions crates/uv-installer/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ impl<'a> Planner<'a> {
tags: &Tags,
) -> Result<Plan> {
// Index all the already-downloaded wheels in the cache.
let mut registry_index = RegistryWheelIndex::new(cache, tags, index_locations, hasher);
let mut registry_index =
RegistryWheelIndex::new(cache, tags, index_locations, hasher, config_settings);
let built_index = BuiltWheelIndex::new(cache, tags, hasher, config_settings);

let mut cached = vec![];
Expand Down Expand Up @@ -248,7 +249,7 @@ impl<'a> Planner<'a> {
}
Some(&entry.dist)
}) {
debug!("Requirement already cached: {distribution}");
debug!("Registry requirement already cached: {distribution}");
cached.push(CachedDist::Registry(distribution.clone()));
continue;
}
Expand Down
84 changes: 83 additions & 1 deletion crates/uv/tests/it/pip_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3251,7 +3251,89 @@ fn launcher_with_symlink() -> Result<()> {
}

#[test]
fn config_settings() {
fn config_settings_registry() {
let context = TestContext::new("3.12");

// Install with a `-C` flag. In this case, the flag has no impact on the build, but uv should
// respect it anyway.
uv_snapshot!(context.filters(), context.pip_install()
.arg("iniconfig")
.arg("--no-binary")
.arg("iniconfig")
.arg("-C=global-option=build_ext"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###
);

// Uninstall the package.
uv_snapshot!(context.filters(), context.pip_uninstall()
.arg("iniconfig"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Uninstalled 1 package in [TIME]
- iniconfig==2.0.0
"###);

// Re-install the package, with the same flag. We should read from the cache.
uv_snapshot!(context.filters(), context.pip_install()
.arg("iniconfig")
.arg("--no-binary")
.arg("iniconfig")
.arg("-C=global-option=build_ext"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###
);

// Uninstall the package.
uv_snapshot!(context.filters(), context.pip_uninstall()
.arg("iniconfig"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Uninstalled 1 package in [TIME]
- iniconfig==2.0.0
"###);

// Re-install the package, without the flag. We should build it from source.
uv_snapshot!(context.filters(), context.pip_install()
.arg("iniconfig")
.arg("--no-binary")
.arg("iniconfig"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"###
);
}

#[test]
fn config_settings_path() {
let context = TestContext::new("3.12");

// Install the editable package.
Expand Down

0 comments on commit b6aa40b

Please sign in to comment.