mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-01 04:17:37 +00:00
uv-resolver: use named fields for some PubGrubPackage variants
I'm planning to add another field here (markers), which puts a lot of stress on the positional approach. So let's just switch over to named fields.
This commit is contained in:
parent
44fe0f6749
commit
eac8221718
8 changed files with 216 additions and 141 deletions
|
|
@ -127,7 +127,7 @@ fn collapse_extra_proxies(
|
|||
) {
|
||||
(
|
||||
DerivationTree::External(External::FromDependencyOf(
|
||||
PubGrubPackage::Extra(..),
|
||||
PubGrubPackage::Extra { .. },
|
||||
..,
|
||||
)),
|
||||
ref mut cause,
|
||||
|
|
@ -138,7 +138,7 @@ fn collapse_extra_proxies(
|
|||
(
|
||||
ref mut cause,
|
||||
DerivationTree::External(External::FromDependencyOf(
|
||||
PubGrubPackage::Extra(..),
|
||||
PubGrubPackage::Extra { .. },
|
||||
..,
|
||||
)),
|
||||
) => {
|
||||
|
|
@ -255,8 +255,8 @@ impl NoSolutionError {
|
|||
BTreeSet::from([python_requirement.target().deref().clone()]),
|
||||
);
|
||||
}
|
||||
PubGrubPackage::Extra(_, _, _) => {}
|
||||
PubGrubPackage::Package(name, _, _) => {
|
||||
PubGrubPackage::Extra { .. } => {}
|
||||
PubGrubPackage::Package { name, .. } => {
|
||||
// Avoid including available versions for packages that exist in the derivation
|
||||
// tree, but were never visited during resolution. We _may_ have metadata for
|
||||
// these packages, but it's non-deterministic, and omitting them ensures that
|
||||
|
|
@ -304,7 +304,7 @@ impl NoSolutionError {
|
|||
) -> Self {
|
||||
let mut new = FxHashMap::default();
|
||||
for package in self.derivation_tree.packages() {
|
||||
if let PubGrubPackage::Package(name, _, _) = package {
|
||||
if let PubGrubPackage::Package { name, .. } = package {
|
||||
if let Some(reason) = unavailable_packages.get(name) {
|
||||
new.insert(name.clone(), reason.clone());
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ impl NoSolutionError {
|
|||
) -> Self {
|
||||
let mut new = FxHashMap::default();
|
||||
for package in self.derivation_tree.packages() {
|
||||
if let PubGrubPackage::Package(name, _, _) = package {
|
||||
if let PubGrubPackage::Package { name, .. } = package {
|
||||
if let Some(versions) = incomplete_packages.get(name) {
|
||||
for entry in versions.iter() {
|
||||
let (version, reason) = entry.pair();
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ fn add_requirements(
|
|||
let PubGrubRequirement { package, version } = result?;
|
||||
|
||||
match &package {
|
||||
PubGrubPackage::Package(name, ..) => {
|
||||
PubGrubPackage::Package { name, .. } => {
|
||||
// Detect self-dependencies.
|
||||
if source_name.is_some_and(|source_name| source_name == name) {
|
||||
warn!("{name} has a dependency on itself");
|
||||
|
|
@ -112,7 +112,7 @@ fn add_requirements(
|
|||
|
||||
dependencies.push((package.clone(), version.clone()));
|
||||
}
|
||||
PubGrubPackage::Extra(name, extra, ..) => {
|
||||
PubGrubPackage::Extra { name, extra, .. } => {
|
||||
// Recursively add the dependencies of the current package (e.g., `black` depending on
|
||||
// `black[colorama]`).
|
||||
if source_name.is_some_and(|source_name| source_name == name) {
|
||||
|
|
@ -158,7 +158,7 @@ fn add_requirements(
|
|||
PubGrubRequirement::from_constraint(constraint, urls, locals)?;
|
||||
|
||||
// Ignore self-dependencies.
|
||||
if let PubGrubPackage::Package(name, ..) = &package {
|
||||
if let PubGrubPackage::Package { name, .. } = &package {
|
||||
// Detect self-dependencies.
|
||||
if source_name.is_some_and(|source_name| source_name == name) {
|
||||
warn!("{name} has a dependency on itself");
|
||||
|
|
@ -244,11 +244,11 @@ impl PubGrubRequirement {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::Package(
|
||||
requirement.name.clone(),
|
||||
package: PubGrubPackage::Package {
|
||||
name: requirement.name.clone(),
|
||||
extra,
|
||||
Some(expected.clone()),
|
||||
),
|
||||
url: Some(expected.clone()),
|
||||
},
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
|
|
@ -269,11 +269,11 @@ impl PubGrubRequirement {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::Package(
|
||||
requirement.name.clone(),
|
||||
package: PubGrubPackage::Package {
|
||||
name: requirement.name.clone(),
|
||||
extra,
|
||||
Some(expected.clone()),
|
||||
),
|
||||
url: Some(expected.clone()),
|
||||
},
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
|
|
@ -294,11 +294,11 @@ impl PubGrubRequirement {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::Package(
|
||||
requirement.name.clone(),
|
||||
package: PubGrubPackage::Package {
|
||||
name: requirement.name.clone(),
|
||||
extra,
|
||||
Some(expected.clone()),
|
||||
),
|
||||
url: Some(expected.clone()),
|
||||
},
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ pub enum PubGrubPackage {
|
|||
/// A Python version.
|
||||
Python(PubGrubPython),
|
||||
/// A Python package.
|
||||
Package(
|
||||
PackageName,
|
||||
Option<ExtraName>,
|
||||
Package {
|
||||
name: PackageName,
|
||||
extra: Option<ExtraName>,
|
||||
/// The URL of the package, if it was specified in the requirement.
|
||||
///
|
||||
/// There are a few challenges that come with URL-based packages, and how they map to
|
||||
|
|
@ -59,8 +59,8 @@ pub enum PubGrubPackage {
|
|||
/// we're going to have a dependency that's provided as a URL, we _need_ to visit the URL
|
||||
/// version before the registry version. So we could just error if we visit a URL variant
|
||||
/// _after_ a registry variant.
|
||||
Option<VerbatimParsedUrl>,
|
||||
),
|
||||
url: Option<VerbatimParsedUrl>,
|
||||
},
|
||||
/// A proxy package to represent a dependency with an extra (e.g., `black[colorama]`).
|
||||
///
|
||||
/// For a given package `black`, and an extra `colorama`, we create a virtual package
|
||||
|
|
@ -74,7 +74,11 @@ pub enum PubGrubPackage {
|
|||
/// the exact same version of the base variant. Without the proxy package, then when provided
|
||||
/// requirements like `black==23.0.1` and `black[colorama]`, PubGrub may attempt to retrieve
|
||||
/// metadata for `black[colorama]` versions other than `23.0.1`.
|
||||
Extra(PackageName, ExtraName, Option<VerbatimParsedUrl>),
|
||||
Extra {
|
||||
name: PackageName,
|
||||
extra: ExtraName,
|
||||
url: Option<VerbatimParsedUrl>,
|
||||
},
|
||||
}
|
||||
|
||||
impl PubGrubPackage {
|
||||
|
|
@ -82,9 +86,9 @@ impl PubGrubPackage {
|
|||
pub(crate) fn from_package(name: PackageName, extra: Option<ExtraName>, urls: &Urls) -> Self {
|
||||
let url = urls.get(&name).cloned();
|
||||
if let Some(extra) = extra {
|
||||
Self::Extra(name, extra, url)
|
||||
Self::Extra { name, extra, url }
|
||||
} else {
|
||||
Self::Package(name, extra, url)
|
||||
Self::Package { name, extra, url }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -108,11 +112,17 @@ impl std::fmt::Display for PubGrubPackage {
|
|||
}
|
||||
}
|
||||
Self::Python(_) => write!(f, "Python"),
|
||||
Self::Package(name, None, ..) => write!(f, "{name}"),
|
||||
Self::Package(name, Some(extra), ..) => {
|
||||
Self::Package {
|
||||
name, extra: None, ..
|
||||
} => write!(f, "{name}"),
|
||||
Self::Package {
|
||||
name,
|
||||
extra: Some(extra),
|
||||
..
|
||||
} => {
|
||||
write!(f, "{name}[{extra}]")
|
||||
}
|
||||
Self::Extra(name, extra, ..) => write!(f, "{name}[{extra}]"),
|
||||
Self::Extra { name, extra, .. } => write!(f, "{name}[{extra}]"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,12 @@ impl PubGrubPriorities {
|
|||
PubGrubPackage::Root(_) => {}
|
||||
PubGrubPackage::Python(_) => {}
|
||||
|
||||
PubGrubPackage::Extra(name, _, None) | PubGrubPackage::Package(name, _, None) => {
|
||||
PubGrubPackage::Extra {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackage::Package {
|
||||
name, url: None, ..
|
||||
} => {
|
||||
match self.0.entry(name.clone()) {
|
||||
std::collections::hash_map::Entry::Occupied(mut entry) => {
|
||||
// Preserve the original index.
|
||||
|
|
@ -61,7 +66,12 @@ impl PubGrubPriorities {
|
|||
}
|
||||
}
|
||||
}
|
||||
PubGrubPackage::Extra(name, _, Some(_)) | PubGrubPackage::Package(name, _, Some(_)) => {
|
||||
PubGrubPackage::Extra {
|
||||
name, url: Some(_), ..
|
||||
}
|
||||
| PubGrubPackage::Package {
|
||||
name, url: Some(_), ..
|
||||
} => {
|
||||
match self.0.entry(name.clone()) {
|
||||
std::collections::hash_map::Entry::Occupied(mut entry) => {
|
||||
// Preserve the original index.
|
||||
|
|
@ -94,8 +104,8 @@ impl PubGrubPriorities {
|
|||
match package {
|
||||
PubGrubPackage::Root(_) => Some(PubGrubPriority::Root),
|
||||
PubGrubPackage::Python(_) => Some(PubGrubPriority::Root),
|
||||
PubGrubPackage::Extra(name, _, _) => self.0.get(name).copied(),
|
||||
PubGrubPackage::Package(name, _, _) => self.0.get(name).copied(),
|
||||
PubGrubPackage::Extra { name, .. } => self.0.get(name).copied(),
|
||||
PubGrubPackage::Package { name, .. } => self.0.get(name).copied(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,14 +155,14 @@ impl ReportFormatter<PubGrubPackage, Range<Version>, UnavailableReason>
|
|||
let terms_vec: Vec<_> = terms.iter().collect();
|
||||
match terms_vec.as_slice() {
|
||||
[] | [(PubGrubPackage::Root(_), _)] => "the requirements are unsatisfiable".into(),
|
||||
[(package @ PubGrubPackage::Package(..), Term::Positive(range))] => {
|
||||
[(package @ PubGrubPackage::Package { .. }, Term::Positive(range))] => {
|
||||
let range = self.simplify_set(range, package);
|
||||
format!(
|
||||
"{} cannot be used",
|
||||
PackageRange::compatibility(package, &range)
|
||||
)
|
||||
}
|
||||
[(package @ PubGrubPackage::Package(..), Term::Negative(range))] => {
|
||||
[(package @ PubGrubPackage::Package { .. }, Term::Negative(range))] => {
|
||||
let range = self.simplify_set(range, package);
|
||||
format!(
|
||||
"{} must be used",
|
||||
|
|
@ -399,10 +399,10 @@ impl PubGrubReportFormatter<'_> {
|
|||
) -> IndexSet<PubGrubHint> {
|
||||
/// Returns `true` if pre-releases were allowed for a package.
|
||||
fn allowed_prerelease(package: &PubGrubPackage, selector: &CandidateSelector) -> bool {
|
||||
let PubGrubPackage::Package(package, ..) = package else {
|
||||
let PubGrubPackage::Package { name, .. } = package else {
|
||||
return false;
|
||||
};
|
||||
selector.prerelease_strategy().allows(package)
|
||||
selector.prerelease_strategy().allows(name)
|
||||
}
|
||||
|
||||
let mut hints = IndexSet::default();
|
||||
|
|
@ -457,7 +457,7 @@ impl PubGrubReportFormatter<'_> {
|
|||
let no_find_links =
|
||||
index_locations.flat_index().peekable().peek().is_none();
|
||||
|
||||
if let PubGrubPackage::Package(name, ..) = package {
|
||||
if let PubGrubPackage::Package { name, .. } = package {
|
||||
// Add hints due to the package being entirely unavailable.
|
||||
match unavailable_packages.get(name) {
|
||||
Some(UnavailablePackage::NoIndex) => {
|
||||
|
|
|
|||
|
|
@ -56,8 +56,12 @@ impl ResolutionGraph {
|
|||
let mut diagnostics = Vec::new();
|
||||
for (package, version) in selection {
|
||||
match package {
|
||||
PubGrubPackage::Package(package_name, Some(extra), None) => {
|
||||
let dist = PubGrubDistribution::from_registry(package_name, version);
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
extra: Some(extra),
|
||||
url: None,
|
||||
} => {
|
||||
let dist = PubGrubDistribution::from_registry(name, version);
|
||||
|
||||
let response = distributions.get(&dist.version_id()).unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
|
@ -75,15 +79,13 @@ impl ResolutionGraph {
|
|||
|
||||
if archive.metadata.provides_extras.contains(extra) {
|
||||
extras
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(extra.clone());
|
||||
} else {
|
||||
let dist = pins
|
||||
.get(package_name, version)
|
||||
.unwrap_or_else(|| {
|
||||
panic!("Every package should be pinned: {package_name:?}")
|
||||
})
|
||||
.get(name, version)
|
||||
.unwrap_or_else(|| panic!("Every package should be pinned: {name:?}"))
|
||||
.clone();
|
||||
|
||||
diagnostics.push(Diagnostic::MissingExtra {
|
||||
|
|
@ -92,16 +94,19 @@ impl ResolutionGraph {
|
|||
});
|
||||
}
|
||||
}
|
||||
PubGrubPackage::Package(package_name, Some(extra), Some(url)) => {
|
||||
if let Some(editable) = editables.get(package_name) {
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
extra: Some(extra),
|
||||
url: Some(url),
|
||||
} => {
|
||||
if let Some(editable) = editables.get(name) {
|
||||
if editable.metadata.provides_extras.contains(extra) {
|
||||
extras
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(extra.clone());
|
||||
} else {
|
||||
let dist =
|
||||
Dist::from_editable(package_name.clone(), editable.built.clone())?;
|
||||
let dist = Dist::from_editable(name.clone(), editable.built.clone())?;
|
||||
|
||||
diagnostics.push(Diagnostic::MissingExtra {
|
||||
dist: dist.into(),
|
||||
|
|
@ -109,7 +114,7 @@ impl ResolutionGraph {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
let dist = PubGrubDistribution::from_url(package_name, url);
|
||||
let dist = PubGrubDistribution::from_url(name, url);
|
||||
|
||||
let response = distributions.get(&dist.version_id()).unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
|
@ -127,12 +132,11 @@ impl ResolutionGraph {
|
|||
|
||||
if archive.metadata.provides_extras.contains(extra) {
|
||||
extras
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(extra.clone());
|
||||
} else {
|
||||
let dist =
|
||||
Dist::from_url(package_name.clone(), url_to_precise(url.clone()))?;
|
||||
let dist = Dist::from_url(name.clone(), url_to_precise(url.clone()))?;
|
||||
|
||||
diagnostics.push(Diagnostic::MissingExtra {
|
||||
dist: dist.into(),
|
||||
|
|
@ -154,21 +158,25 @@ impl ResolutionGraph {
|
|||
|
||||
for (package, version) in selection {
|
||||
match package {
|
||||
PubGrubPackage::Package(package_name, None, None) => {
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
extra: None,
|
||||
url: None,
|
||||
} => {
|
||||
// Create the distribution.
|
||||
let dist = pins
|
||||
.get(package_name, version)
|
||||
.get(name, version)
|
||||
.expect("Every package should be pinned")
|
||||
.clone();
|
||||
|
||||
// Extract the hashes, preserving those that were already present in the
|
||||
// lockfile if necessary.
|
||||
let hashes = if let Some(digests) = preferences
|
||||
.match_hashes(package_name, version)
|
||||
.match_hashes(name, version)
|
||||
.filter(|digests| !digests.is_empty())
|
||||
{
|
||||
digests.to_vec()
|
||||
} else if let Some(versions_response) = packages.get(package_name) {
|
||||
} else if let Some(versions_response) = packages.get(name) {
|
||||
if let VersionsResponse::Found(ref version_maps) = *versions_response {
|
||||
version_maps
|
||||
.iter()
|
||||
|
|
@ -187,7 +195,7 @@ impl ResolutionGraph {
|
|||
|
||||
// Extract the metadata.
|
||||
let metadata = {
|
||||
let dist = PubGrubDistribution::from_registry(package_name, version);
|
||||
let dist = PubGrubDistribution::from_registry(name, version);
|
||||
|
||||
let response = distributions.get(&dist.version_id()).unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
|
@ -207,7 +215,7 @@ impl ResolutionGraph {
|
|||
};
|
||||
|
||||
// Extract the extras.
|
||||
let extras = extras.get(package_name).cloned().unwrap_or_default();
|
||||
let extras = extras.get(name).cloned().unwrap_or_default();
|
||||
|
||||
// Add the distribution to the graph.
|
||||
let index = petgraph.add_node(AnnotatedDist {
|
||||
|
|
@ -216,13 +224,16 @@ impl ResolutionGraph {
|
|||
hashes,
|
||||
metadata,
|
||||
});
|
||||
inverse.insert(package_name, index);
|
||||
inverse.insert(name, index);
|
||||
}
|
||||
PubGrubPackage::Package(package_name, None, Some(url)) => {
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
extra: None,
|
||||
url: Some(url),
|
||||
} => {
|
||||
// Create the distribution.
|
||||
if let Some(editable) = editables.get(package_name) {
|
||||
let dist =
|
||||
Dist::from_editable(package_name.clone(), editable.built.clone())?;
|
||||
if let Some(editable) = editables.get(name) {
|
||||
let dist = Dist::from_editable(name.clone(), editable.built.clone())?;
|
||||
|
||||
// Add the distribution to the graph.
|
||||
let index = petgraph.add_node(AnnotatedDist {
|
||||
|
|
@ -231,15 +242,14 @@ impl ResolutionGraph {
|
|||
hashes: vec![],
|
||||
metadata: editable.metadata.clone(),
|
||||
});
|
||||
inverse.insert(package_name, index);
|
||||
inverse.insert(name, index);
|
||||
} else {
|
||||
let dist =
|
||||
Dist::from_url(package_name.clone(), url_to_precise(url.clone()))?;
|
||||
let dist = Dist::from_url(name.clone(), url_to_precise(url.clone()))?;
|
||||
|
||||
// Extract the hashes, preserving those that were already present in the
|
||||
// lockfile if necessary.
|
||||
let hashes = if let Some(digests) = preferences
|
||||
.match_hashes(package_name, version)
|
||||
.match_hashes(name, version)
|
||||
.filter(|digests| !digests.is_empty())
|
||||
{
|
||||
digests.to_vec()
|
||||
|
|
@ -259,7 +269,7 @@ impl ResolutionGraph {
|
|||
|
||||
// Extract the metadata.
|
||||
let metadata = {
|
||||
let dist = PubGrubDistribution::from_url(package_name, url);
|
||||
let dist = PubGrubDistribution::from_url(name, url);
|
||||
|
||||
let response =
|
||||
distributions.get(&dist.version_id()).unwrap_or_else(|| {
|
||||
|
|
@ -280,7 +290,7 @@ impl ResolutionGraph {
|
|||
};
|
||||
|
||||
// Extract the extras.
|
||||
let extras = extras.get(package_name).cloned().unwrap_or_default();
|
||||
let extras = extras.get(name).cloned().unwrap_or_default();
|
||||
|
||||
// Add the distribution to the graph.
|
||||
let index = petgraph.add_node(AnnotatedDist {
|
||||
|
|
@ -289,7 +299,7 @@ impl ResolutionGraph {
|
|||
hashes,
|
||||
metadata,
|
||||
});
|
||||
inverse.insert(package_name, index);
|
||||
inverse.insert(name, index);
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -314,22 +324,28 @@ impl ResolutionGraph {
|
|||
continue;
|
||||
}
|
||||
|
||||
let PubGrubPackage::Package(self_package, _, _) = self_package else {
|
||||
let PubGrubPackage::Package {
|
||||
name: self_name, ..
|
||||
} = self_package
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let PubGrubPackage::Package(dependency_package, _, _) = dependency_package
|
||||
let PubGrubPackage::Package {
|
||||
name: dependency_name,
|
||||
..
|
||||
} = dependency_package
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// For extras, we include a dependency between the extra and the base package.
|
||||
if self_package == dependency_package {
|
||||
if self_name == dependency_name {
|
||||
continue;
|
||||
}
|
||||
|
||||
if self_version.contains(version) {
|
||||
let self_index = &inverse[self_package];
|
||||
let dependency_index = &inverse[dependency_package];
|
||||
let self_index = &inverse[self_name];
|
||||
let dependency_index = &inverse[dependency_name];
|
||||
petgraph.update_edge(
|
||||
*self_index,
|
||||
*dependency_index,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,12 @@ impl BatchPrefetcher {
|
|||
index: &InMemoryIndex,
|
||||
selector: &CandidateSelector,
|
||||
) -> anyhow::Result<(), ResolveError> {
|
||||
let PubGrubPackage::Package(package_name, None, None) = &next else {
|
||||
let PubGrubPackage::Package {
|
||||
name,
|
||||
extra: None,
|
||||
url: None,
|
||||
} = &next
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
|
|
@ -66,7 +71,7 @@ impl BatchPrefetcher {
|
|||
// This is immediate, we already fetched the version map.
|
||||
let versions_response = index
|
||||
.packages()
|
||||
.wait_blocking(package_name)
|
||||
.wait_blocking(name)
|
||||
.ok_or(ResolveError::Unregistered)?;
|
||||
|
||||
let VersionsResponse::Found(ref version_map) = *versions_response else {
|
||||
|
|
@ -85,7 +90,7 @@ impl BatchPrefetcher {
|
|||
previous,
|
||||
} => {
|
||||
if let Some(candidate) =
|
||||
selector.select_no_preference(package_name, &compatible, version_map)
|
||||
selector.select_no_preference(name, &compatible, version_map)
|
||||
{
|
||||
let compatible = compatible.intersection(
|
||||
&Range::singleton(candidate.version().clone()).complement(),
|
||||
|
|
@ -103,13 +108,13 @@ impl BatchPrefetcher {
|
|||
}
|
||||
}
|
||||
BatchPrefetchStrategy::InOrder { previous } => {
|
||||
let range = if selector.use_highest_version(package_name) {
|
||||
let range = if selector.use_highest_version(name) {
|
||||
Range::strictly_lower_than(previous)
|
||||
} else {
|
||||
Range::strictly_higher_than(previous)
|
||||
};
|
||||
if let Some(candidate) =
|
||||
selector.select_no_preference(package_name, &range, version_map)
|
||||
selector.select_no_preference(name, &range, version_map)
|
||||
{
|
||||
phase = BatchPrefetchStrategy::InOrder {
|
||||
previous: candidate.version().clone(),
|
||||
|
|
@ -148,7 +153,7 @@ impl BatchPrefetcher {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("Prefetching {prefetch_count} {package_name} versions");
|
||||
debug!("Prefetching {prefetch_count} {name} versions");
|
||||
|
||||
self.last_prefetch.insert(next.clone(), num_tried);
|
||||
Ok(())
|
||||
|
|
@ -157,7 +162,7 @@ impl BatchPrefetcher {
|
|||
/// Each time we tried a version for a package, we register that here.
|
||||
pub(crate) fn version_tried(&mut self, package: PubGrubPackage) {
|
||||
// Only track base packages, no virtual packages from extras.
|
||||
if matches!(package, PubGrubPackage::Package(_, Some(_), _)) {
|
||||
if matches!(package, PubGrubPackage::Package { extra: Some(_), .. }) {
|
||||
return;
|
||||
}
|
||||
*self.tried_versions.entry(package).or_default() += 1;
|
||||
|
|
|
|||
|
|
@ -480,8 +480,8 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
.expect("a package was chosen but we don't have a term.");
|
||||
|
||||
// Check if the decision was due to the package being unavailable
|
||||
if let PubGrubPackage::Package(ref package_name, _, _) = state.next {
|
||||
if let Some(entry) = self.unavailable_packages.get(package_name) {
|
||||
if let PubGrubPackage::Package { ref name, .. } = state.next {
|
||||
if let Some(entry) = self.unavailable_packages.get(name) {
|
||||
state
|
||||
.pubgrub
|
||||
.add_incompatibility(Incompatibility::custom_term(
|
||||
|
|
@ -636,8 +636,10 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
match package {
|
||||
PubGrubPackage::Root(_) => {}
|
||||
PubGrubPackage::Python(_) => {}
|
||||
PubGrubPackage::Extra(_, _, _) => {}
|
||||
PubGrubPackage::Package(name, _extra, None) => {
|
||||
PubGrubPackage::Extra { .. } => {}
|
||||
PubGrubPackage::Package {
|
||||
name, url: None, ..
|
||||
} => {
|
||||
// Verify that the package is allowed under the hash-checking policy.
|
||||
if !self.hasher.allows_package(name) {
|
||||
return Err(ResolveError::UnhashedPackage(name.clone()));
|
||||
|
|
@ -648,7 +650,11 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
request_sink.blocking_send(Request::Package(name.clone()))?;
|
||||
}
|
||||
}
|
||||
PubGrubPackage::Package(name, _extra, Some(url)) => {
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
} => {
|
||||
// Verify that the package is allowed under the hash-checking policy.
|
||||
if !self.hasher.allows_url(&url.verbatim) {
|
||||
return Err(ResolveError::UnhashedPackage(name.clone()));
|
||||
|
|
@ -678,10 +684,15 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
// Iterate over the potential packages, and fetch file metadata for any of them. These
|
||||
// represent our current best guesses for the versions that we _might_ select.
|
||||
for (package, range) in packages {
|
||||
let PubGrubPackage::Package(package_name, None, None) = package else {
|
||||
let PubGrubPackage::Package {
|
||||
name,
|
||||
extra: None,
|
||||
url: None,
|
||||
} = package
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
request_sink.blocking_send(Request::Prefetch(package_name.clone(), range.clone()))?;
|
||||
request_sink.blocking_send(Request::Prefetch(name.clone(), range.clone()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -720,15 +731,23 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
}
|
||||
}
|
||||
|
||||
PubGrubPackage::Extra(package_name, _, Some(url))
|
||||
| PubGrubPackage::Package(package_name, _, Some(url)) => {
|
||||
PubGrubPackage::Extra {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
}
|
||||
| PubGrubPackage::Package {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
} => {
|
||||
debug!(
|
||||
"Searching for a compatible version of {package} @ {} ({range})",
|
||||
url.verbatim
|
||||
);
|
||||
|
||||
// If the dist is an editable, return the version from the editable metadata.
|
||||
if let Some(editable) = self.editables.get(package_name) {
|
||||
if let Some(editable) = self.editables.get(name) {
|
||||
let version = &editable.metadata.version;
|
||||
|
||||
// The version is incompatible with the requirement.
|
||||
|
|
@ -752,7 +771,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
return Ok(Some(ResolverVersion::Available(version.clone())));
|
||||
}
|
||||
|
||||
let dist = PubGrubDistribution::from_url(package_name, url);
|
||||
let dist = PubGrubDistribution::from_url(name, url);
|
||||
let response = self
|
||||
.index
|
||||
.distributions()
|
||||
|
|
@ -764,26 +783,26 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
MetadataResponse::Found(archive) => &archive.metadata,
|
||||
MetadataResponse::Offline => {
|
||||
self.unavailable_packages
|
||||
.insert(package_name.clone(), UnavailablePackage::Offline);
|
||||
.insert(name.clone(), UnavailablePackage::Offline);
|
||||
return Ok(None);
|
||||
}
|
||||
MetadataResponse::InvalidMetadata(err) => {
|
||||
self.unavailable_packages.insert(
|
||||
package_name.clone(),
|
||||
name.clone(),
|
||||
UnavailablePackage::InvalidMetadata(err.to_string()),
|
||||
);
|
||||
return Ok(None);
|
||||
}
|
||||
MetadataResponse::InconsistentMetadata(err) => {
|
||||
self.unavailable_packages.insert(
|
||||
package_name.clone(),
|
||||
name.clone(),
|
||||
UnavailablePackage::InvalidMetadata(err.to_string()),
|
||||
);
|
||||
return Ok(None);
|
||||
}
|
||||
MetadataResponse::InvalidStructure(err) => {
|
||||
self.unavailable_packages.insert(
|
||||
package_name.clone(),
|
||||
name.clone(),
|
||||
UnavailablePackage::InvalidStructure(err.to_string()),
|
||||
);
|
||||
return Ok(None);
|
||||
|
|
@ -813,31 +832,35 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
Ok(Some(ResolverVersion::Available(version.clone())))
|
||||
}
|
||||
|
||||
PubGrubPackage::Extra(package_name, _, None)
|
||||
| PubGrubPackage::Package(package_name, _, None) => {
|
||||
PubGrubPackage::Extra {
|
||||
name, url: None, ..
|
||||
}
|
||||
| PubGrubPackage::Package {
|
||||
name, url: None, ..
|
||||
} => {
|
||||
// Wait for the metadata to be available.
|
||||
let versions_response = self
|
||||
.index
|
||||
.packages()
|
||||
.wait_blocking(package_name)
|
||||
.wait_blocking(name)
|
||||
.ok_or(ResolveError::Unregistered)?;
|
||||
visited.insert(package_name.clone());
|
||||
visited.insert(name.clone());
|
||||
|
||||
let version_maps = match *versions_response {
|
||||
VersionsResponse::Found(ref version_maps) => version_maps.as_slice(),
|
||||
VersionsResponse::NoIndex => {
|
||||
self.unavailable_packages
|
||||
.insert(package_name.clone(), UnavailablePackage::NoIndex);
|
||||
.insert(name.clone(), UnavailablePackage::NoIndex);
|
||||
&[]
|
||||
}
|
||||
VersionsResponse::Offline => {
|
||||
self.unavailable_packages
|
||||
.insert(package_name.clone(), UnavailablePackage::Offline);
|
||||
.insert(name.clone(), UnavailablePackage::Offline);
|
||||
&[]
|
||||
}
|
||||
VersionsResponse::NotFound => {
|
||||
self.unavailable_packages
|
||||
.insert(package_name.clone(), UnavailablePackage::NotFound);
|
||||
.insert(name.clone(), UnavailablePackage::NotFound);
|
||||
&[]
|
||||
}
|
||||
};
|
||||
|
|
@ -846,7 +869,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
|
||||
// Find a version.
|
||||
let Some(candidate) = self.selector.select(
|
||||
package_name,
|
||||
name,
|
||||
range,
|
||||
version_maps,
|
||||
&self.preferences,
|
||||
|
|
@ -892,7 +915,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
let version = candidate.version().clone();
|
||||
|
||||
// Emit a request to fetch the metadata for this version.
|
||||
if matches!(package, PubGrubPackage::Package(_, _, _)) {
|
||||
if matches!(package, PubGrubPackage::Package { .. }) {
|
||||
if self.index.distributions().register(candidate.version_id()) {
|
||||
let request = Request::from(dist.for_resolution());
|
||||
request_sink.blocking_send(request)?;
|
||||
|
|
@ -997,16 +1020,16 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
|
||||
PubGrubPackage::Python(_) => Ok(Dependencies::Available(Vec::default())),
|
||||
|
||||
PubGrubPackage::Package(package_name, extra, url) => {
|
||||
PubGrubPackage::Package { name, extra, url } => {
|
||||
// If we're excluding transitive dependencies, short-circuit.
|
||||
if self.dependency_mode.is_direct() {
|
||||
// If an extra is provided, wait for the metadata to be available, since it's
|
||||
// still required for generating the lock file.
|
||||
if !self.editables.contains(package_name) {
|
||||
if !self.editables.contains(name) {
|
||||
// Determine the distribution to lookup.
|
||||
let dist = match url {
|
||||
Some(url) => PubGrubDistribution::from_url(package_name, url),
|
||||
None => PubGrubDistribution::from_registry(package_name, version),
|
||||
Some(url) => PubGrubDistribution::from_url(name, url),
|
||||
None => PubGrubDistribution::from_registry(name, version),
|
||||
};
|
||||
let version_id = dist.version_id();
|
||||
|
||||
|
|
@ -1021,7 +1044,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
}
|
||||
|
||||
// Determine if the distribution is editable.
|
||||
if let Some(editable) = self.editables.get(package_name) {
|
||||
if let Some(editable) = self.editables.get(name) {
|
||||
let requirements: Vec<_> = editable
|
||||
.metadata
|
||||
.requires_dist
|
||||
|
|
@ -1033,7 +1056,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
&requirements,
|
||||
&self.constraints,
|
||||
&self.overrides,
|
||||
Some(package_name),
|
||||
Some(name),
|
||||
extra.as_ref(),
|
||||
&self.urls,
|
||||
&self.locals,
|
||||
|
|
@ -1055,24 +1078,21 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
|
||||
// Determine the distribution to lookup.
|
||||
let dist = match url {
|
||||
Some(url) => PubGrubDistribution::from_url(package_name, url),
|
||||
None => PubGrubDistribution::from_registry(package_name, version),
|
||||
Some(url) => PubGrubDistribution::from_url(name, url),
|
||||
None => PubGrubDistribution::from_registry(name, version),
|
||||
};
|
||||
let version_id = dist.version_id();
|
||||
|
||||
// If the package does not exist in the registry or locally, we cannot fetch its dependencies
|
||||
if self.unavailable_packages.get(package_name).is_some()
|
||||
&& self
|
||||
.installed_packages
|
||||
.get_packages(package_name)
|
||||
.is_empty()
|
||||
if self.unavailable_packages.get(name).is_some()
|
||||
&& self.installed_packages.get_packages(name).is_empty()
|
||||
{
|
||||
debug_assert!(
|
||||
false,
|
||||
"Dependencies were requested for a package that is not available"
|
||||
);
|
||||
return Err(ResolveError::Failure(format!(
|
||||
"The package is unavailable: {package_name}"
|
||||
"The package is unavailable: {name}"
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -1087,15 +1107,15 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
MetadataResponse::Found(archive) => &archive.metadata,
|
||||
MetadataResponse::Offline => {
|
||||
self.incomplete_packages
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.insert(version.clone(), IncompletePackage::Offline);
|
||||
return Ok(Dependencies::Unavailable(UnavailableVersion::Offline));
|
||||
}
|
||||
MetadataResponse::InvalidMetadata(err) => {
|
||||
warn!("Unable to extract metadata for {package_name}: {err}");
|
||||
warn!("Unable to extract metadata for {name}: {err}");
|
||||
self.incomplete_packages
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.insert(
|
||||
version.clone(),
|
||||
|
|
@ -1106,9 +1126,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
));
|
||||
}
|
||||
MetadataResponse::InconsistentMetadata(err) => {
|
||||
warn!("Unable to extract metadata for {package_name}: {err}");
|
||||
warn!("Unable to extract metadata for {name}: {err}");
|
||||
self.incomplete_packages
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.insert(
|
||||
version.clone(),
|
||||
|
|
@ -1119,9 +1139,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
));
|
||||
}
|
||||
MetadataResponse::InvalidStructure(err) => {
|
||||
warn!("Unable to extract metadata for {package_name}: {err}");
|
||||
warn!("Unable to extract metadata for {name}: {err}");
|
||||
self.incomplete_packages
|
||||
.entry(package_name.clone())
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.insert(
|
||||
version.clone(),
|
||||
|
|
@ -1143,7 +1163,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
&requirements,
|
||||
&self.constraints,
|
||||
&self.overrides,
|
||||
Some(package_name),
|
||||
Some(name),
|
||||
extra.as_ref(),
|
||||
&self.urls,
|
||||
&self.locals,
|
||||
|
|
@ -1164,13 +1184,21 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
}
|
||||
|
||||
// Add a dependency on both the extra and base package.
|
||||
PubGrubPackage::Extra(package_name, extra, url) => Ok(Dependencies::Available(vec![
|
||||
PubGrubPackage::Extra { name, extra, url } => Ok(Dependencies::Available(vec![
|
||||
(
|
||||
PubGrubPackage::Package(package_name.clone(), None, url.clone()),
|
||||
PubGrubPackage::Package {
|
||||
name: name.clone(),
|
||||
extra: None,
|
||||
url: url.clone(),
|
||||
},
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
(
|
||||
PubGrubPackage::Package(package_name.clone(), Some(extra.clone()), url.clone()),
|
||||
PubGrubPackage::Package {
|
||||
name: name.clone(),
|
||||
extra: Some(extra.clone()),
|
||||
url: url.clone(),
|
||||
},
|
||||
Range::singleton(version.clone()),
|
||||
),
|
||||
])),
|
||||
|
|
@ -1398,12 +1426,18 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
match package {
|
||||
PubGrubPackage::Root(_) => {}
|
||||
PubGrubPackage::Python(_) => {}
|
||||
PubGrubPackage::Extra(_, _, _) => {}
|
||||
PubGrubPackage::Package(package_name, _extra, Some(url)) => {
|
||||
reporter.on_progress(package_name, &VersionOrUrlRef::Url(&url.verbatim));
|
||||
PubGrubPackage::Extra { .. } => {}
|
||||
PubGrubPackage::Package {
|
||||
name,
|
||||
url: Some(url),
|
||||
..
|
||||
} => {
|
||||
reporter.on_progress(name, &VersionOrUrlRef::Url(&url.verbatim));
|
||||
}
|
||||
PubGrubPackage::Package(package_name, _extra, None) => {
|
||||
reporter.on_progress(package_name, &VersionOrUrlRef::Version(version));
|
||||
PubGrubPackage::Package {
|
||||
name, url: None, ..
|
||||
} => {
|
||||
reporter.on_progress(name, &VersionOrUrlRef::Version(version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue