Show full derivation chain when encountering build failures (#9108)

## Summary

This PR adds context to our error messages to explain _why_ a given
package was included, if we fail to download or build it.

It's quite a large change, but it motivated some good refactors and
improvements along the way.

Closes https://github.com/astral-sh/uv/issues/8962.
This commit is contained in:
Charlie Marsh 2024-11-14 15:48:26 -05:00 committed by GitHub
parent a552f74308
commit fe477c3417
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1147 additions and 172 deletions

View file

@ -29,8 +29,8 @@ use uv_installer::{Installer, Plan, Planner, Preparer, SitePackages};
use uv_pypi_types::{Conflicts, Requirement};
use uv_python::{Interpreter, PythonEnvironment};
use uv_resolver::{
ExcludeNewer, FlatIndex, Flexibility, InMemoryIndex, Manifest, OptionsBuilder,
PythonRequirement, Resolver, ResolverEnvironment,
DerivationChainBuilder, ExcludeNewer, FlatIndex, Flexibility, InMemoryIndex, Manifest,
OptionsBuilder, PythonRequirement, Resolver, ResolverEnvironment,
};
use uv_types::{BuildContext, BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
@ -278,7 +278,33 @@ impl<'a> BuildContext for BuildDispatch<'a> {
remote.iter().map(ToString::to_string).join(", ")
);
preparer.prepare(remote, self.in_flight).await?
preparer
.prepare(remote, self.in_flight)
.await
.map_err(|err| match err {
uv_installer::PrepareError::DownloadAndBuild(dist, chain, err) => {
debug_assert!(chain.is_empty());
let chain =
DerivationChainBuilder::from_resolution(resolution, (&*dist).into())
.unwrap_or_default();
uv_installer::PrepareError::DownloadAndBuild(dist, chain, err)
}
uv_installer::PrepareError::Download(dist, chain, err) => {
debug_assert!(chain.is_empty());
let chain =
DerivationChainBuilder::from_resolution(resolution, (&*dist).into())
.unwrap_or_default();
uv_installer::PrepareError::Download(dist, chain, err)
}
uv_installer::PrepareError::Build(dist, chain, err) => {
debug_assert!(chain.is_empty());
let chain =
DerivationChainBuilder::from_resolution(resolution, (&*dist).into())
.unwrap_or_default();
uv_installer::PrepareError::Build(dist, chain, err)
}
_ => err,
})?
};
// Remove any unnecessary packages.