mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
Surface PubGrub derivation trees (#108)
I think the derivation trees could be stronger but this exposes PubGrub's proof-like error messages. Closes #102.
This commit is contained in:
parent
bae52d5edd
commit
5f5788e866
7 changed files with 50 additions and 14 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1826,6 +1826,7 @@ dependencies = [
|
|||
"pep508_rs",
|
||||
"platform-host",
|
||||
"platform-tags",
|
||||
"pubgrub",
|
||||
"puffin-client",
|
||||
"puffin-installer",
|
||||
"puffin-interpreter",
|
||||
|
|
|
@ -14,6 +14,7 @@ pep440_rs = { path = "../pep440-rs" }
|
|||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
platform-tags = { path = "../platform-tags" }
|
||||
pubgrub = { path = "../../vendor/pubgrub" }
|
||||
puffin-client = { path = "../puffin-client" }
|
||||
puffin-installer = { path = "../puffin-installer" }
|
||||
puffin-interpreter = { path = "../puffin-interpreter" }
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::path::Path;
|
|||
|
||||
use anyhow::Result;
|
||||
use colored::Colorize;
|
||||
use pubgrub::report::Reporter;
|
||||
use tracing::debug;
|
||||
|
||||
use platform_host::Platform;
|
||||
|
@ -62,7 +63,23 @@ pub(crate) async fn compile(
|
|||
|
||||
// Resolve the dependencies.
|
||||
let resolver = puffin_resolver::Resolver::new(requirements, markers, &tags, &client);
|
||||
let resolution = resolver.resolve().await?;
|
||||
let resolution = match resolver.resolve().await {
|
||||
Err(puffin_resolver::ResolveError::PubGrub(pubgrub::error::PubGrubError::NoSolution(
|
||||
mut derivation_tree,
|
||||
))) => {
|
||||
derivation_tree.collapse_no_versions();
|
||||
#[allow(clippy::print_stderr)]
|
||||
{
|
||||
eprintln!("{}: {}", "error".red().bold(), "no solution found".bold());
|
||||
eprintln!(
|
||||
"{}",
|
||||
pubgrub::report::DefaultStringReporter::report(&derivation_tree)
|
||||
);
|
||||
}
|
||||
return Ok(ExitStatus::Failure);
|
||||
}
|
||||
result => result,
|
||||
}?;
|
||||
|
||||
let s = if resolution.len() == 1 { "" } else { "s" };
|
||||
writeln!(
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use std::path::PathBuf;
|
||||
use std::process::ExitCode;
|
||||
|
||||
use crate::commands::ExitStatus;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use colored::Colorize;
|
||||
use directories::ProjectDirs;
|
||||
|
||||
use crate::commands::ExitStatus;
|
||||
|
||||
mod commands;
|
||||
mod logging;
|
||||
mod printer;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub use error::ResolveError;
|
||||
pub use resolution::{PinnedPackage, Resolution};
|
||||
pub use resolver::Resolver;
|
||||
pub use wheel_finder::{Reporter, WheelFinder};
|
||||
|
|
|
@ -17,7 +17,7 @@ pub enum PubGrubPackage {
|
|||
impl std::fmt::Display for PubGrubPackage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PubGrubPackage::Root => write!(f, "<root>"),
|
||||
PubGrubPackage::Root => write!(f, "root"),
|
||||
PubGrubPackage::Package(name, None) => write!(f, "{name}"),
|
||||
PubGrubPackage::Package(name, Some(extra)) => {
|
||||
write!(f, "{name}[{extra}]")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Given a set of requirements, find a set of compatible packages.
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
@ -158,16 +159,13 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
// Fetch the list of candidates.
|
||||
let Some(potential_packages) = state.partial_solution.potential_packages() else {
|
||||
let Some(selected_dependencies) = state.partial_solution.extract_solution() else {
|
||||
let Some(selection) = state.partial_solution.extract_solution() else {
|
||||
return Err(PubGrubError::Failure(
|
||||
"How did we end up with no package to choose but no solution?".into(),
|
||||
)
|
||||
.into());
|
||||
};
|
||||
return Ok(PubGrubResolution {
|
||||
selected_dependencies,
|
||||
pins,
|
||||
});
|
||||
return Ok(PubGrubResolution { selection, pins });
|
||||
};
|
||||
|
||||
// Choose a package version.
|
||||
|
@ -415,12 +413,23 @@ impl<'a> Resolver<'a> {
|
|||
for (package, version) in
|
||||
iter_requirements(self.requirements.iter(), None, self.markers)
|
||||
{
|
||||
constraints.insert(package, version);
|
||||
match constraints.entry(package) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.insert(entry.get().intersection(&version));
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Dependencies::Known(constraints))
|
||||
}
|
||||
PubGrubPackage::Package(package_name, extra) => {
|
||||
debug!("Fetching dependencies for {}[{:?}]", package_name, extra);
|
||||
if let Some(extra) = extra.as_ref() {
|
||||
debug!("Fetching dependencies for {}[{:?}]", package_name, extra);
|
||||
} else {
|
||||
debug!("Fetching dependencies for {}", package_name);
|
||||
}
|
||||
|
||||
// Wait for the metadata to be available.
|
||||
let versions = pins.get(package_name).unwrap();
|
||||
|
@ -429,7 +438,6 @@ impl<'a> Resolver<'a> {
|
|||
let metadata = entry.value();
|
||||
|
||||
let mut constraints = DependencyConstraints::default();
|
||||
|
||||
for (package, version) in
|
||||
iter_requirements(metadata.requires_dist.iter(), extra.as_ref(), self.markers)
|
||||
{
|
||||
|
@ -443,7 +451,14 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
// Add it to the constraints.
|
||||
constraints.insert(package, version);
|
||||
match constraints.entry(package) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
entry.insert(entry.get().intersection(&version));
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(extra) = extra {
|
||||
|
@ -512,7 +527,7 @@ enum Dependencies {
|
|||
#[derive(Debug)]
|
||||
struct PubGrubResolution {
|
||||
/// The selected dependencies.
|
||||
selected_dependencies: SelectedDependencies<PubGrubPackage, PubGrubVersion>,
|
||||
selection: SelectedDependencies<PubGrubPackage, PubGrubVersion>,
|
||||
/// The selected file (source or built distribution) for each package.
|
||||
pins: HashMap<PackageName, HashMap<pep440_rs::Version, File>>,
|
||||
}
|
||||
|
@ -520,7 +535,7 @@ struct PubGrubResolution {
|
|||
impl From<PubGrubResolution> for Resolution {
|
||||
fn from(value: PubGrubResolution) -> Self {
|
||||
let mut packages = BTreeMap::new();
|
||||
for (package, version) in value.selected_dependencies {
|
||||
for (package, version) in value.selection {
|
||||
let PubGrubPackage::Package(package_name, None) = package else {
|
||||
continue;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue