mirror of https://github.com/astral-sh/uv
Upgrade PubGrub to 02a19f72d636119fb3f826a922122e21da69cfa5
This commit is contained in:
parent
cfd84d6365
commit
c4e108136d
|
|
@ -1,90 +0,0 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
use pubgrub::package::Package;
|
|
||||||
use pubgrub::range::Range;
|
|
||||||
use pubgrub::solver::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider};
|
|
||||||
use pubgrub::version::NumberVersion;
|
|
||||||
use pubgrub::version_set::VersionSet;
|
|
||||||
|
|
||||||
type NumVS = Range<NumberVersion>;
|
|
||||||
|
|
||||||
// An example implementing caching dependency provider that will
|
|
||||||
// store queried dependencies in memory and check them before querying more from remote.
|
|
||||||
struct CachingDependencyProvider<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>> {
|
|
||||||
remote_dependencies: DP,
|
|
||||||
cached_dependencies: RefCell<OfflineDependencyProvider<P, VS>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>>
|
|
||||||
CachingDependencyProvider<P, VS, DP>
|
|
||||||
{
|
|
||||||
pub fn new(remote_dependencies_provider: DP) -> Self {
|
|
||||||
CachingDependencyProvider {
|
|
||||||
remote_dependencies: remote_dependencies_provider,
|
|
||||||
cached_dependencies: RefCell::new(OfflineDependencyProvider::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>> DependencyProvider<P, VS>
|
|
||||||
for CachingDependencyProvider<P, VS, DP>
|
|
||||||
{
|
|
||||||
// Caches dependencies if they were already queried
|
|
||||||
fn get_dependencies(
|
|
||||||
&self,
|
|
||||||
package: &P,
|
|
||||||
version: &VS::V,
|
|
||||||
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>> {
|
|
||||||
let mut cache = self.cached_dependencies.borrow_mut();
|
|
||||||
match cache.get_dependencies(package, version) {
|
|
||||||
Ok(Dependencies::Unknown) => {
|
|
||||||
let dependencies = self.remote_dependencies.get_dependencies(package, version);
|
|
||||||
match dependencies {
|
|
||||||
Ok(Dependencies::Known(dependencies)) => {
|
|
||||||
cache.add_dependencies(
|
|
||||||
package.clone(),
|
|
||||||
version.clone(),
|
|
||||||
dependencies.clone(),
|
|
||||||
);
|
|
||||||
Ok(Dependencies::Known(dependencies))
|
|
||||||
}
|
|
||||||
Ok(Dependencies::Unknown) => Ok(Dependencies::Unknown),
|
|
||||||
error @ Err(_) => error,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dependencies @ Ok(_) => dependencies,
|
|
||||||
error @ Err(_) => error,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_version(
|
|
||||||
&self,
|
|
||||||
package: &P,
|
|
||||||
range: &VS,
|
|
||||||
) -> Result<Option<VS::V>, Box<dyn Error + Send + Sync>> {
|
|
||||||
self.remote_dependencies.choose_version(package, range)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Priority = DP::Priority;
|
|
||||||
|
|
||||||
fn prioritize(&self, package: &P, range: &VS) -> Self::Priority {
|
|
||||||
self.remote_dependencies.prioritize(package, range)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// Simulating remote provider locally.
|
|
||||||
let mut remote_dependencies_provider = OfflineDependencyProvider::<&str, NumVS>::new();
|
|
||||||
|
|
||||||
// Add dependencies as needed. Here only root package is added.
|
|
||||||
remote_dependencies_provider.add_dependencies("root", 1, Vec::new());
|
|
||||||
|
|
||||||
let caching_dependencies_provider =
|
|
||||||
CachingDependencyProvider::new(remote_dependencies_provider);
|
|
||||||
|
|
||||||
let solution = resolve(&caching_dependencies_provider, "root", 1);
|
|
||||||
println!("Solution: {:?}", solution);
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,7 @@ use crate::internal::partial_solution::{DecisionLevel, PartialSolution};
|
||||||
use crate::internal::small_vec::SmallVec;
|
use crate::internal::small_vec::SmallVec;
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
use crate::report::DerivationTree;
|
use crate::report::DerivationTree;
|
||||||
use crate::type_aliases::{DependencyConstraints, Map};
|
use crate::type_aliases::Map;
|
||||||
use crate::version_set::VersionSet;
|
use crate::version_set::VersionSet;
|
||||||
|
|
||||||
/// Current state of the PubGrub algorithm.
|
/// Current state of the PubGrub algorithm.
|
||||||
|
|
@ -24,7 +24,7 @@ pub struct State<P: Package, VS: VersionSet, Priority: Ord + Clone> {
|
||||||
root_package: P,
|
root_package: P,
|
||||||
root_version: VS::V,
|
root_version: VS::V,
|
||||||
|
|
||||||
pub incompatibilities: Map<P, Vec<IncompId<P, VS>>>,
|
incompatibilities: Map<P, Vec<IncompId<P, VS>>>,
|
||||||
|
|
||||||
/// Store the ids of incompatibilities that are already contradicted
|
/// Store the ids of incompatibilities that are already contradicted
|
||||||
/// and will stay that way until the next conflict and backtrack is operated.
|
/// and will stay that way until the next conflict and backtrack is operated.
|
||||||
|
|
@ -75,12 +75,12 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
|
||||||
&mut self,
|
&mut self,
|
||||||
package: P,
|
package: P,
|
||||||
version: VS::V,
|
version: VS::V,
|
||||||
deps: &DependencyConstraints<P, VS>,
|
deps: impl IntoIterator<Item = (P, VS)>,
|
||||||
) -> std::ops::Range<IncompId<P, VS>> {
|
) -> std::ops::Range<IncompId<P, VS>> {
|
||||||
// Create incompatibilities and allocate them in the store.
|
// Create incompatibilities and allocate them in the store.
|
||||||
let new_incompats_id_range = self
|
let new_incompats_id_range = self
|
||||||
.incompatibility_store
|
.incompatibility_store
|
||||||
.alloc_iter(deps.iter().map(|dep| {
|
.alloc_iter(deps.into_iter().map(|dep| {
|
||||||
Incompatibility::from_dependency(package.clone(), version.clone(), dep)
|
Incompatibility::from_dependency(package.clone(), version.clone(), dep)
|
||||||
}));
|
}));
|
||||||
// Merge the newly created incompatibilities with the older ones.
|
// Merge the newly created incompatibilities with the older ones.
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ use crate::version_set::VersionSet;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Incompatibility<P: Package, VS: VersionSet> {
|
pub struct Incompatibility<P: Package, VS: VersionSet> {
|
||||||
package_terms: SmallMap<P, Term<VS>>,
|
package_terms: SmallMap<P, Term<VS>>,
|
||||||
pub kind: Kind<P, VS>,
|
kind: Kind<P, VS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type alias of unique identifiers for incompatibilities.
|
/// Type alias of unique identifiers for incompatibilities.
|
||||||
pub type IncompId<P, VS> = Id<Incompatibility<P, VS>>;
|
pub type IncompId<P, VS> = Id<Incompatibility<P, VS>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Kind<P: Package, VS: VersionSet> {
|
enum Kind<P: Package, VS: VersionSet> {
|
||||||
/// Initial incompatibility aiming at picking the root package for the first decision.
|
/// Initial incompatibility aiming at picking the root package for the first decision.
|
||||||
NotRoot(P, VS::V),
|
NotRoot(P, VS::V),
|
||||||
/// There are no versions in the given range for this package.
|
/// There are no versions in the given range for this package.
|
||||||
|
|
@ -105,11 +105,11 @@ impl<P: Package, VS: VersionSet> Incompatibility<P, VS> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build an incompatibility from a given dependency.
|
/// Build an incompatibility from a given dependency.
|
||||||
pub fn from_dependency(package: P, version: VS::V, dep: (&P, &VS)) -> Self {
|
pub fn from_dependency(package: P, version: VS::V, dep: (P, VS)) -> Self {
|
||||||
let set1 = VS::singleton(version);
|
let set1 = VS::singleton(version);
|
||||||
let (p2, set2) = dep;
|
let (p2, set2) = dep;
|
||||||
Self {
|
Self {
|
||||||
package_terms: if set2 == &VS::empty() {
|
package_terms: if set2 == VS::empty() {
|
||||||
SmallMap::One([(package.clone(), Term::Positive(set1.clone()))])
|
SmallMap::One([(package.clone(), Term::Positive(set1.clone()))])
|
||||||
} else {
|
} else {
|
||||||
SmallMap::Two([
|
SmallMap::Two([
|
||||||
|
|
@ -117,7 +117,7 @@ impl<P: Package, VS: VersionSet> Incompatibility<P, VS> {
|
||||||
(p2.clone(), Term::Negative(set2.clone())),
|
(p2.clone(), Term::Negative(set2.clone())),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
kind: Kind::FromDependencyOf(package, set1, p2.clone(), set2.clone()),
|
kind: Kind::FromDependencyOf(package, set1, p2, set2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,24 +252,6 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prioritized_packages(&self) -> impl Iterator<Item = (&P, &VS)> {
|
|
||||||
let check_all = self.changed_this_decision_level
|
|
||||||
== self.current_decision_level.0.saturating_sub(1) as usize;
|
|
||||||
let current_decision_level = self.current_decision_level;
|
|
||||||
self.package_assignments
|
|
||||||
.get_range(self.changed_this_decision_level..)
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.filter(move |(_, pa)| {
|
|
||||||
// We only actually need to update the package if its Been changed
|
|
||||||
// since the last time we called prioritize.
|
|
||||||
// Which means it's highest decision level is the current decision level,
|
|
||||||
// or if we backtracked in the mean time.
|
|
||||||
check_all || pa.highest_decision_level == current_decision_level
|
|
||||||
})
|
|
||||||
.filter_map(|(p, pa)| pa.assignments_intersection.potential_package_filter(p))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pick_highest_priority_pkg(
|
pub fn pick_highest_priority_pkg(
|
||||||
&mut self,
|
&mut self,
|
||||||
prioritizer: impl Fn(&P, &VS) -> Priority,
|
prioritizer: impl Fn(&P, &VS) -> Priority,
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,10 @@
|
||||||
//! &self,
|
//! &self,
|
||||||
//! package: &String,
|
//! package: &String,
|
||||||
//! version: &SemanticVersion,
|
//! version: &SemanticVersion,
|
||||||
//! ) -> Result<Dependencies<String, SemVS>, Box<dyn Error + Send + Sync>> {
|
//! ) -> Result<Dependencies<impl IntoIterator<Item = (String, SemVS)> + Clone>, Box<dyn Error + Send + Sync>>
|
||||||
//! unimplemented!()
|
//! {
|
||||||
|
//! unimplemented!();
|
||||||
|
//! Ok(Dependencies::Known([]))
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
@ -217,7 +219,8 @@
|
||||||
//! with a cache, you may want to know that some versions
|
//! with a cache, you may want to know that some versions
|
||||||
//! do not exist in your cache.
|
//! do not exist in your cache.
|
||||||
|
|
||||||
#![allow(clippy::all, unreachable_pub)]
|
#![allow(clippy::rc_buffer)]
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod package;
|
pub mod package;
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ impl<V: Ord> Range<V> {
|
||||||
.segments
|
.segments
|
||||||
.last()
|
.last()
|
||||||
.expect("if there is a first element, there must be a last element");
|
.expect("if there is a first element, there must be a last element");
|
||||||
(bound_as_ref(start), bound_as_ref(&end.1))
|
(start.as_ref(), end.1.as_ref())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,15 +264,6 @@ impl<V: Ord> Range<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of [`Bound::as_ref`] which is currently marked as unstable.
|
|
||||||
fn bound_as_ref<V>(bound: &Bound<V>) -> Bound<&V> {
|
|
||||||
match bound {
|
|
||||||
Included(v) => Included(v),
|
|
||||||
Excluded(v) => Excluded(v),
|
|
||||||
Unbounded => Unbounded,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn valid_segment<T: PartialOrd>(start: &Bound<T>, end: &Bound<T>) -> bool {
|
fn valid_segment<T: PartialOrd>(start: &Bound<T>, end: &Bound<T>) -> bool {
|
||||||
match (start, end) {
|
match (start, end) {
|
||||||
(Included(s), Included(e)) => s <= e,
|
(Included(s), Included(e)) => s <= e,
|
||||||
|
|
@ -307,7 +298,7 @@ impl<V: Ord + Clone> Range<V> {
|
||||||
|
|
||||||
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i <= e => Excluded(e),
|
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i <= e => Excluded(e),
|
||||||
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e < i => Included(i),
|
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e < i => Included(i),
|
||||||
(s, Unbounded) | (Unbounded, s) => bound_as_ref(s),
|
(s, Unbounded) | (Unbounded, s) => s.as_ref(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
@ -317,7 +308,7 @@ impl<V: Ord + Clone> Range<V> {
|
||||||
|
|
||||||
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i >= e => Excluded(e),
|
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i >= e => Excluded(e),
|
||||||
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e > i => Included(i),
|
(Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e > i => Included(i),
|
||||||
(s, Unbounded) | (Unbounded, s) => bound_as_ref(s),
|
(s, Unbounded) | (Unbounded, s) => s.as_ref(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
@ -373,7 +364,7 @@ impl<V: Display + Eq> Display for Range<V> {
|
||||||
} else {
|
} else {
|
||||||
for (idx, segment) in self.segments.iter().enumerate() {
|
for (idx, segment) in self.segments.iter().enumerate() {
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
write!(f, ", ")?;
|
write!(f, " | ")?;
|
||||||
}
|
}
|
||||||
match segment {
|
match segment {
|
||||||
(Unbounded, Unbounded) => write!(f, "*")?,
|
(Unbounded, Unbounded) => write!(f, "*")?,
|
||||||
|
|
@ -382,9 +373,9 @@ impl<V: Display + Eq> Display for Range<V> {
|
||||||
(Included(v), Unbounded) => write!(f, ">={v}")?,
|
(Included(v), Unbounded) => write!(f, ">={v}")?,
|
||||||
(Included(v), Included(b)) => {
|
(Included(v), Included(b)) => {
|
||||||
if v == b {
|
if v == b {
|
||||||
write!(f, "=={v}")?
|
write!(f, "{v}")?
|
||||||
} else {
|
} else {
|
||||||
write!(f, ">={v},<={b}")?
|
write!(f, ">={v}, <={b}")?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Included(v), Excluded(b)) => write!(f, ">={v}, <{b}")?,
|
(Included(v), Excluded(b)) => write!(f, ">={v}, <{b}")?,
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,10 @@ use std::collections::{BTreeMap, BTreeSet as Set};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::error::PubGrubError;
|
use crate::error::PubGrubError;
|
||||||
pub use crate::internal::core::State;
|
use crate::internal::core::State;
|
||||||
pub use crate::internal::incompatibility::{Incompatibility, Kind};
|
use crate::internal::incompatibility::Incompatibility;
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
use crate::type_aliases::{DependencyConstraints, Map, SelectedDependencies};
|
use crate::type_aliases::{Map, SelectedDependencies};
|
||||||
use crate::version_set::VersionSet;
|
use crate::version_set::VersionSet;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
|
||||||
|
|
@ -162,10 +162,10 @@ pub fn resolve<P: Package, VS: VersionSet>(
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Dependencies::Known(x) if x.contains_key(p) => {
|
Dependencies::Known(x) if x.clone().into_iter().any(|(d, _)| &d == p) => {
|
||||||
return Err(PubGrubError::SelfDependency {
|
return Err(PubGrubError::SelfDependency {
|
||||||
package: p.clone(),
|
package: p.clone(),
|
||||||
version: v,
|
version: v.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Dependencies::Known(x) => x,
|
Dependencies::Known(x) => x,
|
||||||
|
|
@ -175,12 +175,12 @@ pub fn resolve<P: Package, VS: VersionSet>(
|
||||||
let dep_incompats = state.add_incompatibility_from_dependencies(
|
let dep_incompats = state.add_incompatibility_from_dependencies(
|
||||||
p.clone(),
|
p.clone(),
|
||||||
v.clone(),
|
v.clone(),
|
||||||
&known_dependencies,
|
known_dependencies,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.partial_solution.add_version(
|
state.partial_solution.add_version(
|
||||||
p.clone(),
|
p.clone(),
|
||||||
v,
|
v.clone(),
|
||||||
dep_incompats,
|
dep_incompats,
|
||||||
&state.incompatibility_store,
|
&state.incompatibility_store,
|
||||||
);
|
);
|
||||||
|
|
@ -196,11 +196,11 @@ pub fn resolve<P: Package, VS: VersionSet>(
|
||||||
/// An enum used by [DependencyProvider] that holds information about package dependencies.
|
/// An enum used by [DependencyProvider] that holds information about package dependencies.
|
||||||
/// For each [Package] there is a set of versions allowed as a dependency.
|
/// For each [Package] there is a set of versions allowed as a dependency.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Dependencies<P: Package, VS: VersionSet> {
|
pub enum Dependencies<T> {
|
||||||
/// Package dependencies are unavailable.
|
/// Package dependencies are unavailable.
|
||||||
Unknown,
|
Unknown,
|
||||||
/// Container for all available package versions.
|
/// Container for all available package versions.
|
||||||
Known(DependencyConstraints<P, VS>),
|
Known(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that allows the algorithm to retrieve available packages and their dependencies.
|
/// Trait that allows the algorithm to retrieve available packages and their dependencies.
|
||||||
|
|
@ -255,7 +255,7 @@ pub trait DependencyProvider<P: Package, VS: VersionSet> {
|
||||||
&self,
|
&self,
|
||||||
package: &P,
|
package: &P,
|
||||||
version: &VS::V,
|
version: &VS::V,
|
||||||
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>>;
|
) -> Result<Dependencies<impl IntoIterator<Item = (P, VS)> + Clone>, Box<dyn Error + Send + Sync>>;
|
||||||
|
|
||||||
/// This is called fairly regularly during the resolution,
|
/// This is called fairly regularly during the resolution,
|
||||||
/// if it returns an Err then resolution will be terminated.
|
/// if it returns an Err then resolution will be terminated.
|
||||||
|
|
@ -279,7 +279,7 @@ pub trait DependencyProvider<P: Package, VS: VersionSet> {
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||||
pub struct OfflineDependencyProvider<P: Package, VS: VersionSet> {
|
pub struct OfflineDependencyProvider<P: Package, VS: VersionSet> {
|
||||||
dependencies: Map<P, BTreeMap<VS::V, DependencyConstraints<P, VS>>>,
|
dependencies: Map<P, BTreeMap<VS::V, Map<P, VS>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Package, VS: VersionSet> OfflineDependencyProvider<P, VS> {
|
impl<P: Package, VS: VersionSet> OfflineDependencyProvider<P, VS> {
|
||||||
|
|
@ -329,8 +329,8 @@ impl<P: Package, VS: VersionSet> OfflineDependencyProvider<P, VS> {
|
||||||
|
|
||||||
/// Lists dependencies of a given package and version.
|
/// Lists dependencies of a given package and version.
|
||||||
/// Returns [None] if no information is available regarding that package and version pair.
|
/// Returns [None] if no information is available regarding that package and version pair.
|
||||||
fn dependencies(&self, package: &P, version: &VS::V) -> Option<DependencyConstraints<P, VS>> {
|
fn dependencies(&self, package: &P, version: &VS::V) -> Option<&Map<P, VS>> {
|
||||||
self.dependencies.get(package)?.get(version).cloned()
|
self.dependencies.get(package)?.get(version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,11 +364,16 @@ impl<P: Package, VS: VersionSet> DependencyProvider<P, VS> for OfflineDependency
|
||||||
fn get_dependencies(
|
fn get_dependencies(
|
||||||
&self,
|
&self,
|
||||||
package: &P,
|
package: &P,
|
||||||
version: &VS::V,
|
version: &<VS as VersionSet>::V,
|
||||||
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Dependencies<impl IntoIterator<Item = (P, VS)> + Clone>, Box<dyn Error + Send + Sync>>
|
||||||
|
{
|
||||||
Ok(match self.dependencies(package, version) {
|
Ok(match self.dependencies(package, version) {
|
||||||
None => Dependencies::Unknown,
|
None => Dependencies::Unknown,
|
||||||
Some(dependencies) => Dependencies::Known(dependencies),
|
Some(dependencies) => Dependencies::Known(
|
||||||
|
dependencies
|
||||||
|
.into_iter()
|
||||||
|
.map(|(p, vs)| (p.clone(), vs.clone())),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ impl<VS: VersionSet> Term<VS> {
|
||||||
|
|
||||||
/// Unwrap the set contained in a positive term.
|
/// Unwrap the set contained in a positive term.
|
||||||
/// Will panic if used on a negative set.
|
/// Will panic if used on a negative set.
|
||||||
pub fn unwrap_positive(&self) -> &VS {
|
pub(crate) fn unwrap_positive(&self) -> &VS {
|
||||||
match self {
|
match self {
|
||||||
Self::Positive(set) => set,
|
Self::Positive(set) => set,
|
||||||
_ => panic!("Negative term cannot unwrap positive set"),
|
_ => panic!("Negative term cannot unwrap positive set"),
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,3 @@ pub type Map<K, V> = rustc_hash::FxHashMap<K, V>;
|
||||||
/// Concrete dependencies picked by the library during [resolve](crate::solver::resolve)
|
/// Concrete dependencies picked by the library during [resolve](crate::solver::resolve)
|
||||||
/// from [DependencyConstraints].
|
/// from [DependencyConstraints].
|
||||||
pub type SelectedDependencies<P, V> = Map<P, V>;
|
pub type SelectedDependencies<P, V> = Map<P, V>;
|
||||||
|
|
||||||
/// Holds information about all possible versions a given package can accept.
|
|
||||||
/// There is a difference in semantics between an empty map
|
|
||||||
/// inside [DependencyConstraints] and [Dependencies::Unknown](crate::solver::Dependencies::Unknown):
|
|
||||||
/// the former means the package has no dependency and it is a known fact,
|
|
||||||
/// while the latter means they could not be fetched by the [DependencyProvider](crate::solver::DependencyProvider).
|
|
||||||
pub type DependencyConstraints<P, VS> = Map<P, VS>;
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ impl<P: Package, VS: VersionSet> DependencyProvider<P, VS>
|
||||||
&self,
|
&self,
|
||||||
p: &P,
|
p: &P,
|
||||||
v: &VS::V,
|
v: &VS::V,
|
||||||
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Dependencies<impl IntoIterator<Item = (P, VS)> + Clone>, Box<dyn Error + Send + Sync>>
|
||||||
|
{
|
||||||
self.0.get_dependencies(p, v)
|
self.0.get_dependencies(p, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +87,8 @@ impl<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>> DependencyProvid
|
||||||
&self,
|
&self,
|
||||||
p: &P,
|
p: &P,
|
||||||
v: &VS::V,
|
v: &VS::V,
|
||||||
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>> {
|
) -> Result<Dependencies<impl IntoIterator<Item = (P, VS)> + Clone>, Box<dyn Error + Send + Sync>>
|
||||||
|
{
|
||||||
self.dp.get_dependencies(p, v)
|
self.dp.get_dependencies(p, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,8 +347,8 @@ fn retain_dependencies<N: Package + Ord, VS: VersionSet>(
|
||||||
smaller_dependency_provider.add_dependencies(
|
smaller_dependency_provider.add_dependencies(
|
||||||
n.clone(),
|
n.clone(),
|
||||||
v.clone(),
|
v.clone(),
|
||||||
deps.iter().filter_map(|(dep, range)| {
|
deps.into_iter().filter_map(|(dep, range)| {
|
||||||
if !retain(n, v, dep) {
|
if !retain(n, v, &dep) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((dep.clone(), range.clone()))
|
Some((dep.clone(), range.clone()))
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,10 @@ impl<P: Package, VS: VersionSet> SatResolve<P, VS> {
|
||||||
Dependencies::Unknown => panic!(),
|
Dependencies::Unknown => panic!(),
|
||||||
Dependencies::Known(d) => d,
|
Dependencies::Known(d) => d,
|
||||||
};
|
};
|
||||||
for (p1, range) in &deps {
|
for (p1, range) in deps {
|
||||||
let empty_vec = vec![];
|
let empty_vec = vec![];
|
||||||
let mut matches: Vec<varisat::Lit> = all_versions_by_p
|
let mut matches: Vec<varisat::Lit> = all_versions_by_p
|
||||||
.get(p1)
|
.get(&p1)
|
||||||
.unwrap_or(&empty_vec)
|
.unwrap_or(&empty_vec)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(v1, _)| range.contains(v1))
|
.filter(|(v1, _)| range.contains(v1))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue