mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-18 06:18:53 +00:00
Read cached registry distributions when --config-settings
are present (#10578)
## Summary Closes https://github.com/astral-sh/uv/issues/10577.
This commit is contained in:
parent
53d3d5e3b8
commit
b6aa40b29d
3 changed files with 104 additions and 6 deletions
|
@ -3,6 +3,8 @@ use std::collections::hash_map::Entry;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use uv_cache::{Cache, CacheBucket, WheelCache};
|
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_distribution_types::{CachedRegistryDist, Hashed, Index, IndexLocations, IndexUrl};
|
||||||
use uv_fs::{directories, files, symlinks};
|
use uv_fs::{directories, files, symlinks};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
|
@ -31,6 +33,7 @@ pub struct RegistryWheelIndex<'a> {
|
||||||
index_locations: &'a IndexLocations,
|
index_locations: &'a IndexLocations,
|
||||||
hasher: &'a HashStrategy,
|
hasher: &'a HashStrategy,
|
||||||
index: FxHashMap<&'a PackageName, Vec<IndexEntry<'a>>>,
|
index: FxHashMap<&'a PackageName, Vec<IndexEntry<'a>>>,
|
||||||
|
build_configuration: &'a ConfigSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RegistryWheelIndex<'a> {
|
impl<'a> RegistryWheelIndex<'a> {
|
||||||
|
@ -40,12 +43,14 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
tags: &'a Tags,
|
tags: &'a Tags,
|
||||||
index_locations: &'a IndexLocations,
|
index_locations: &'a IndexLocations,
|
||||||
hasher: &'a HashStrategy,
|
hasher: &'a HashStrategy,
|
||||||
|
build_configuration: &'a ConfigSettings,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache,
|
cache,
|
||||||
tags,
|
tags,
|
||||||
index_locations,
|
index_locations,
|
||||||
hasher,
|
hasher,
|
||||||
|
build_configuration,
|
||||||
index: FxHashMap::default(),
|
index: FxHashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +72,7 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
self.tags,
|
self.tags,
|
||||||
self.index_locations,
|
self.index_locations,
|
||||||
self.hasher,
|
self.hasher,
|
||||||
|
self.build_configuration,
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
versions
|
versions
|
||||||
|
@ -79,6 +85,7 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
tags: &Tags,
|
tags: &Tags,
|
||||||
index_locations: &'index IndexLocations,
|
index_locations: &'index IndexLocations,
|
||||||
hasher: &HashStrategy,
|
hasher: &HashStrategy,
|
||||||
|
build_configuration: &ConfigSettings,
|
||||||
) -> Vec<IndexEntry<'index>> {
|
) -> Vec<IndexEntry<'index>> {
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
|
|
||||||
|
@ -162,9 +169,8 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
WheelCache::Index(index.url()).wheel_dir(package.to_string()),
|
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) {
|
for shard in directories(&cache_shard) {
|
||||||
// Read the existing metadata from the cache, if it exists.
|
|
||||||
let cache_shard = cache_shard.shard(shard);
|
let cache_shard = cache_shard.shard(shard);
|
||||||
|
|
||||||
// Read the revision from the cache.
|
// Read the revision from the cache.
|
||||||
|
@ -190,7 +196,16 @@ impl<'a> RegistryWheelIndex<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(revision) = revision {
|
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 let Some(wheel) = CachedWheel::from_built_source(wheel_dir) {
|
||||||
if wheel.filename.compatibility(tags).is_compatible() {
|
if wheel.filename.compatibility(tags).is_compatible() {
|
||||||
// Enforce hash-checking based on the source distribution.
|
// Enforce hash-checking based on the source distribution.
|
||||||
|
|
|
@ -56,7 +56,8 @@ impl<'a> Planner<'a> {
|
||||||
tags: &Tags,
|
tags: &Tags,
|
||||||
) -> Result<Plan> {
|
) -> Result<Plan> {
|
||||||
// Index all the already-downloaded wheels in the cache.
|
// 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 built_index = BuiltWheelIndex::new(cache, tags, hasher, config_settings);
|
||||||
|
|
||||||
let mut cached = vec![];
|
let mut cached = vec![];
|
||||||
|
@ -248,7 +249,7 @@ impl<'a> Planner<'a> {
|
||||||
}
|
}
|
||||||
Some(&entry.dist)
|
Some(&entry.dist)
|
||||||
}) {
|
}) {
|
||||||
debug!("Requirement already cached: {distribution}");
|
debug!("Registry requirement already cached: {distribution}");
|
||||||
cached.push(CachedDist::Registry(distribution.clone()));
|
cached.push(CachedDist::Registry(distribution.clone()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3251,7 +3251,89 @@ fn launcher_with_symlink() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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");
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
// Install the editable package.
|
// Install the editable package.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue