uv/crates/uv-resolver/src/resolution_mode.rs
Charlie Marsh 26e3511ebd
Respect fork markers in --resolution-mode=lowest-direct (#8839)
## Summary

Previously, given:

```toml
dependencies = [
    "pycountry >= 22.1.10",
    "setuptools >= 50.0.0; python_version>='3.12'"
]
```

We'd solve for the lowest version of setuptools (with _no_ lower-bound
constraint) in the `python_version < '3.12'` complement.

Closes https://github.com/astral-sh/uv/issues/8819.
2024-11-05 21:09:38 +00:00

61 lines
2.2 KiB
Rust

use crate::resolver::{ForkMap, ForkSet};
use crate::{DependencyMode, Manifest, ResolverEnvironment};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum ResolutionMode {
/// Resolve the highest compatible version of each package.
#[default]
Highest,
/// Resolve the lowest compatible version of each package.
Lowest,
/// Resolve the lowest compatible version of any direct dependencies, and the highest
/// compatible version of any transitive dependencies.
LowestDirect,
}
impl std::fmt::Display for ResolutionMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Highest => write!(f, "highest"),
Self::Lowest => write!(f, "lowest"),
Self::LowestDirect => write!(f, "lowest-direct"),
}
}
}
/// Like [`ResolutionMode`], but with any additional information required to select a candidate,
/// like the set of direct dependencies.
#[derive(Debug, Clone)]
pub(crate) enum ResolutionStrategy {
/// Resolve the highest compatible version of each package.
Highest,
/// Resolve the lowest compatible version of each package.
Lowest,
/// Resolve the lowest compatible version of any direct dependencies, and the highest
/// compatible version of any transitive dependencies.
LowestDirect(ForkSet),
}
impl ResolutionStrategy {
pub(crate) fn from_mode(
mode: ResolutionMode,
manifest: &Manifest,
env: &ResolverEnvironment,
dependencies: DependencyMode,
) -> Self {
match mode {
ResolutionMode::Highest => Self::Highest,
ResolutionMode::Lowest => Self::Lowest,
ResolutionMode::LowestDirect => {
let mut first_party = ForkMap::default();
for requirement in manifest.user_requirements(env, dependencies) {
first_party.add(&requirement, ());
}
Self::LowestDirect(first_party)
}
}
}
}