mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 10:58:28 +00:00
Remove derivation chain special casing (#9678)
Instead of modifying the error to replace a dummy derivation chain from construction with the real one, build the error with the real derivation chain directly.
This commit is contained in:
parent
a286e95f44
commit
400839c527
9 changed files with 117 additions and 159 deletions
|
@ -106,11 +106,7 @@ pub enum ResolveError {
|
|||
),
|
||||
|
||||
#[error("Failed to read metadata from installed package `{0}`")]
|
||||
ReadInstalled(
|
||||
Box<InstalledDist>,
|
||||
DerivationChain,
|
||||
#[source] InstalledDistError,
|
||||
),
|
||||
ReadInstalled(Box<InstalledDist>, #[source] InstalledDistError),
|
||||
|
||||
#[error(transparent)]
|
||||
NoSolution(#[from] NoSolutionError),
|
||||
|
|
|
@ -1,88 +1,18 @@
|
|||
use std::collections::VecDeque;
|
||||
use pubgrub::{Id, Kind, State};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use petgraph::visit::EdgeRef;
|
||||
use petgraph::Direction;
|
||||
use pubgrub::{Id, Kind, Range, State};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use uv_distribution_types::{
|
||||
DerivationChain, DerivationStep, DistRef, Edge, Name, Node, Resolution, ResolvedDist,
|
||||
};
|
||||
use uv_distribution_types::{DerivationChain, DerivationStep};
|
||||
use uv_pep440::Version;
|
||||
|
||||
use crate::dependency_provider::UvDependencyProvider;
|
||||
use crate::pubgrub::PubGrubPackage;
|
||||
|
||||
/// A chain of derivation steps from the root package to the current package, to explain why a
|
||||
/// package is included in the resolution.
|
||||
/// Build a [`DerivationChain`] from the pubgrub state, which is available in `uv-resolver`, but not
|
||||
/// in `uv-distribution-types`.
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct DerivationChainBuilder;
|
||||
|
||||
impl DerivationChainBuilder {
|
||||
/// Compute a [`DerivationChain`] from a resolution graph.
|
||||
///
|
||||
/// This is used to construct a derivation chain upon install failure in the `uv pip` context,
|
||||
/// where we don't have a lockfile describing the resolution.
|
||||
pub fn from_resolution(
|
||||
resolution: &Resolution,
|
||||
target: DistRef<'_>,
|
||||
) -> Option<DerivationChain> {
|
||||
// Find the target distribution in the resolution graph.
|
||||
let target = resolution.graph().node_indices().find(|node| {
|
||||
let Node::Dist {
|
||||
dist: ResolvedDist::Installable { dist, .. },
|
||||
..
|
||||
} = &resolution.graph()[*node]
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
target == dist.as_ref()
|
||||
})?;
|
||||
|
||||
// Perform a BFS to find the shortest path to the root.
|
||||
let mut queue = VecDeque::new();
|
||||
queue.push_back((target, None, None, Vec::new()));
|
||||
|
||||
// TODO(charlie): Consider respecting markers here.
|
||||
let mut seen = FxHashSet::default();
|
||||
while let Some((node, extra, group, mut path)) = queue.pop_front() {
|
||||
if !seen.insert(node) {
|
||||
continue;
|
||||
}
|
||||
match &resolution.graph()[node] {
|
||||
Node::Root => {
|
||||
path.reverse();
|
||||
path.pop();
|
||||
return Some(DerivationChain::from_iter(path));
|
||||
}
|
||||
Node::Dist { dist, .. } => {
|
||||
for edge in resolution.graph().edges_directed(node, Direction::Incoming) {
|
||||
let mut path = path.clone();
|
||||
path.push(DerivationStep::new(
|
||||
dist.name().clone(),
|
||||
extra.clone(),
|
||||
group.clone(),
|
||||
dist.version().clone(),
|
||||
Range::empty(),
|
||||
));
|
||||
let target = edge.source();
|
||||
let extra = match edge.weight() {
|
||||
Edge::Optional(extra, ..) => Some(extra.clone()),
|
||||
_ => None,
|
||||
};
|
||||
let group = match edge.weight() {
|
||||
Edge::Dev(group, ..) => Some(group.clone()),
|
||||
_ => None,
|
||||
};
|
||||
queue.push_back((target, extra, group, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Compute a [`DerivationChain`] from the current PubGrub state.
|
||||
///
|
||||
/// This is used to construct a derivation chain upon resolution failure.
|
||||
|
|
|
@ -1914,13 +1914,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
|
||||
Request::Installed(dist) => {
|
||||
// TODO(charlie): This should be return a `MetadataResponse`.
|
||||
let metadata = dist.metadata().map_err(|err| {
|
||||
ResolveError::ReadInstalled(
|
||||
Box::new(dist.clone()),
|
||||
DerivationChain::default(),
|
||||
err,
|
||||
)
|
||||
})?;
|
||||
let metadata = dist
|
||||
.metadata()
|
||||
.map_err(|err| ResolveError::ReadInstalled(Box::new(dist.clone()), err))?;
|
||||
Ok(Some(Response::Installed { dist, metadata }))
|
||||
}
|
||||
|
||||
|
@ -2035,11 +2031,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
}
|
||||
ResolvedDist::Installed { dist } => {
|
||||
let metadata = dist.metadata().map_err(|err| {
|
||||
ResolveError::ReadInstalled(
|
||||
Box::new(dist.clone()),
|
||||
DerivationChain::default(),
|
||||
err,
|
||||
)
|
||||
ResolveError::ReadInstalled(Box::new(dist.clone()), err)
|
||||
})?;
|
||||
Response::Installed { dist, metadata }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue