mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Make metadata deserialization failures non-fatal in the cache (#11105)
## Summary If we fail to deserialize cached metadata in the cache, we should just ignore it, rather than failing. Ideally, this never happens. If it does, it means we missed a cache version bump. But if it does happen, it should still be non-fatal. Closes https://github.com/astral-sh/uv/issues/11043. Closes https://github.com/astral-sh/uv/issues/11101. ## Test Plan Prior to this PR, the following would fail: - `uvx uv@0.5.25 venv --python 3.12 --cache-dir foo` - `uvx uv@0.5.25 pip install ./scripts/packages/hatchling_dynamic --no-deps --python 3.12 --cache-dir foo` - `uvx uv@0.5.18 venv --python 3.12 --cache-dir foo` - `uvx uv@0.5.18 pip install ./scripts/packages/hatchling_dynamic --no-deps --python 3.12 --cache-dir foo` We can't go back and fix 0.5.18, but this will prevent such regressions in the future.
This commit is contained in:
parent
1dfa650ab4
commit
d106ab1a9a
3 changed files with 91 additions and 64 deletions
|
@ -551,15 +551,21 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
|
||||
// If the cache contains compatible metadata, return it.
|
||||
let metadata_entry = cache_shard.entry(METADATA);
|
||||
if let Some(metadata) = CachedMetadata::read(&metadata_entry)
|
||||
.await?
|
||||
.filter(|metadata| metadata.matches(source.name(), source.version()))
|
||||
{
|
||||
debug!("Using cached metadata for: {source}");
|
||||
return Ok(ArchiveMetadata {
|
||||
metadata: Metadata::from_metadata23(metadata.into()),
|
||||
hashes: revision.into_hashes(),
|
||||
});
|
||||
match CachedMetadata::read(&metadata_entry).await {
|
||||
Ok(Some(metadata)) => {
|
||||
if metadata.matches(source.name(), source.version()) {
|
||||
debug!("Using cached metadata for: {source}");
|
||||
return Ok(ArchiveMetadata {
|
||||
metadata: Metadata::from_metadata23(metadata.into()),
|
||||
hashes: revision.into_hashes(),
|
||||
});
|
||||
}
|
||||
debug!("Cached metadata does not match expected name and version for: {source}");
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
debug!("Failed to deserialize cached metadata for: {source} ({err})");
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we need a wheel.
|
||||
|
@ -882,15 +888,21 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
|
||||
// If the cache contains compatible metadata, return it.
|
||||
let metadata_entry = cache_shard.entry(METADATA);
|
||||
if let Some(metadata) = CachedMetadata::read(&metadata_entry)
|
||||
.await?
|
||||
.filter(|metadata| metadata.matches(source.name(), source.version()))
|
||||
{
|
||||
debug!("Using cached metadata for: {source}");
|
||||
return Ok(ArchiveMetadata {
|
||||
metadata: Metadata::from_metadata23(metadata.into()),
|
||||
hashes: revision.into_hashes(),
|
||||
});
|
||||
match CachedMetadata::read(&metadata_entry).await {
|
||||
Ok(Some(metadata)) => {
|
||||
if metadata.matches(source.name(), source.version()) {
|
||||
debug!("Using cached metadata for: {source}");
|
||||
return Ok(ArchiveMetadata {
|
||||
metadata: Metadata::from_metadata23(metadata.into()),
|
||||
hashes: revision.into_hashes(),
|
||||
});
|
||||
}
|
||||
debug!("Cached metadata does not match expected name and version for: {source}");
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
debug!("Failed to deserialize cached metadata for: {source} ({err})");
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we need a source distribution.
|
||||
|
@ -1183,31 +1195,38 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
|
||||
// If the cache contains compatible metadata, return it.
|
||||
let metadata_entry = cache_shard.entry(METADATA);
|
||||
if let Some(metadata) = CachedMetadata::read(&metadata_entry)
|
||||
.await?
|
||||
.filter(|metadata| metadata.matches(source.name(), source.version()))
|
||||
{
|
||||
// If necessary, mark the metadata as dynamic.
|
||||
let metadata = if dynamic {
|
||||
ResolutionMetadata {
|
||||
dynamic: true,
|
||||
..metadata.into()
|
||||
}
|
||||
} else {
|
||||
metadata.into()
|
||||
};
|
||||
match CachedMetadata::read(&metadata_entry).await {
|
||||
Ok(Some(metadata)) => {
|
||||
if metadata.matches(source.name(), source.version()) {
|
||||
debug!("Using cached metadata for: {source}");
|
||||
|
||||
return Ok(ArchiveMetadata::from(
|
||||
Metadata::from_workspace(
|
||||
metadata,
|
||||
resource.install_path.as_ref(),
|
||||
None,
|
||||
self.build_context.locations(),
|
||||
self.build_context.sources(),
|
||||
self.build_context.bounds(),
|
||||
)
|
||||
.await?,
|
||||
));
|
||||
// If necessary, mark the metadata as dynamic.
|
||||
let metadata = if dynamic {
|
||||
ResolutionMetadata {
|
||||
dynamic: true,
|
||||
..metadata.into()
|
||||
}
|
||||
} else {
|
||||
metadata.into()
|
||||
};
|
||||
return Ok(ArchiveMetadata::from(
|
||||
Metadata::from_workspace(
|
||||
metadata,
|
||||
resource.install_path.as_ref(),
|
||||
None,
|
||||
self.build_context.locations(),
|
||||
self.build_context.sources(),
|
||||
self.build_context.bounds(),
|
||||
)
|
||||
.await?,
|
||||
));
|
||||
}
|
||||
debug!("Cached metadata does not match expected name and version for: {source}");
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
debug!("Failed to deserialize cached metadata for: {source} ({err})");
|
||||
}
|
||||
}
|
||||
|
||||
// If the backend supports `prepare_metadata_for_build_wheel`, use it.
|
||||
|
@ -1635,27 +1654,35 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
|||
.map_err(Error::CacheRead)?
|
||||
.is_fresh()
|
||||
{
|
||||
if let Some(metadata) = CachedMetadata::read(&metadata_entry)
|
||||
.await?
|
||||
.filter(|metadata| metadata.matches(source.name(), source.version()))
|
||||
{
|
||||
let git_member = GitWorkspaceMember {
|
||||
fetch_root: fetch.path(),
|
||||
git_source: resource,
|
||||
};
|
||||
match CachedMetadata::read(&metadata_entry).await {
|
||||
Ok(Some(metadata)) => {
|
||||
if metadata.matches(source.name(), source.version()) {
|
||||
debug!("Using cached metadata for: {source}");
|
||||
|
||||
debug!("Using cached metadata for: {source}");
|
||||
return Ok(ArchiveMetadata::from(
|
||||
Metadata::from_workspace(
|
||||
metadata.into(),
|
||||
&path,
|
||||
Some(&git_member),
|
||||
self.build_context.locations(),
|
||||
self.build_context.sources(),
|
||||
self.build_context.bounds(),
|
||||
)
|
||||
.await?,
|
||||
));
|
||||
let git_member = GitWorkspaceMember {
|
||||
fetch_root: fetch.path(),
|
||||
git_source: resource,
|
||||
};
|
||||
return Ok(ArchiveMetadata::from(
|
||||
Metadata::from_workspace(
|
||||
metadata.into(),
|
||||
&path,
|
||||
Some(&git_member),
|
||||
self.build_context.locations(),
|
||||
self.build_context.sources(),
|
||||
self.build_context.bounds(),
|
||||
)
|
||||
.await?,
|
||||
));
|
||||
}
|
||||
debug!(
|
||||
"Cached metadata does not match expected name and version for: {source}"
|
||||
);
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
debug!("Failed to deserialize cached metadata for: {source} ({err})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue