Add hint for --no-index without --find-links (#1258)

Since unavailable packages with `--no-index` can be confusing when the
user does not also provide `--find-links` we add a hint for this case.
Required some plumbing to get the required information to the
`NoSolution` error.

---------

Co-authored-by: konstin <konstin@mailbox.org>
This commit is contained in:
Zanie Blue 2024-02-06 11:04:14 -06:00 committed by GitHub
parent b2a810fe37
commit d4bbaf1755
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 171 additions and 49 deletions

View file

@ -2,13 +2,14 @@ use std::collections::BTreeSet;
use std::convert::Infallible;
use std::fmt::Formatter;
use dashmap::DashSet;
use dashmap::{DashMap, DashSet};
use indexmap::IndexMap;
use pubgrub::range::Range;
use pubgrub::report::{DefaultStringReporter, DerivationTree, Reporter};
use rustc_hash::FxHashMap;
use url::Url;
use distribution_types::{BuiltDist, PathBuiltDist, PathSourceDist, SourceDist};
use distribution_types::{BuiltDist, IndexLocations, PathBuiltDist, PathSourceDist, SourceDist};
use once_map::OnceMap;
use pep440_rs::Version;
use pep508_rs::Requirement;
@ -17,7 +18,7 @@ use puffin_normalize::PackageName;
use crate::candidate_selector::CandidateSelector;
use crate::pubgrub::{PubGrubPackage, PubGrubPython, PubGrubReportFormatter};
use crate::python_requirement::PythonRequirement;
use crate::resolver::VersionsResponse;
use crate::resolver::{UnavailablePackage, VersionsResponse};
#[derive(Debug, thiserror::Error)]
pub enum ResolveError {
@ -114,6 +115,8 @@ impl From<pubgrub::error::PubGrubError<PubGrubPackage, Range<Version>, Infallibl
available_versions: IndexMap::default(),
selector: None,
python_requirement: None,
index_locations: None,
unavailable_packages: FxHashMap::default(),
})
}
pubgrub::error::PubGrubError::SelfDependency { package, version } => {
@ -133,6 +136,8 @@ pub struct NoSolutionError {
available_versions: IndexMap<PubGrubPackage, BTreeSet<Version>>,
selector: Option<CandidateSelector>,
python_requirement: Option<PythonRequirement>,
index_locations: Option<IndexLocations>,
unavailable_packages: FxHashMap<PackageName, UnavailablePackage>,
}
impl std::error::Error for NoSolutionError {}
@ -149,10 +154,13 @@ impl std::fmt::Display for NoSolutionError {
write!(f, "{report}")?;
// Include any additional hints.
if let Some(selector) = &self.selector {
for hint in formatter.hints(&self.derivation_tree, selector) {
write!(f, "\n\n{hint}")?;
}
for hint in formatter.hints(
&self.derivation_tree,
&self.selector,
&self.index_locations,
&self.unavailable_packages,
) {
write!(f, "\n\n{hint}")?;
}
Ok(())
@ -218,6 +226,32 @@ impl NoSolutionError {
self
}
/// Update the index locations attached to the error.
#[must_use]
pub(crate) fn with_index_locations(mut self, index_locations: &IndexLocations) -> Self {
self.index_locations = Some(index_locations.clone());
self
}
/// Update the unavailable packages attached to the error.
#[must_use]
pub(crate) fn with_unavailable_packages(
mut self,
unavailable_packages: &DashMap<PackageName, UnavailablePackage>,
) -> Self {
let mut new = FxHashMap::default();
for package in self.derivation_tree.packages() {
if let PubGrubPackage::Package(name, ..) = package {
if let Some(entry) = unavailable_packages.get(name) {
let reason = entry.value();
new.insert(name.clone(), reason.clone());
}
}
}
self.unavailable_packages = new;
self
}
/// Update the Python requirements attached to the error.
#[must_use]
pub(crate) fn with_python_requirement(