mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-25 21:37:51 +00:00
## Summary This PR enables overrides to be passed to `pip-compile` and `pip-install` via a new `--overrides` flag. When overrides are provided, we effectively replace any requirements that are overridden with the overridden versions. This is applied at all depths of the tree. The merge semantics are such that we replace _all_ requirements of a package with _all_ requirements from the overrides files. So, for example, if a package declares: ``` foo >= 1.0; python_version < '3.11' foo < 1.0; python_version >= '3.11' ``` And the user provides an override like: ``` foo >= 2.0 ``` Then _both_ of the `foo` requirements in the package will be replaced with the override. If instead, the user provided an override like: ``` foo >= 2.0; python_version < '3.11' foo < 3.0; python_version >= '3.11' ``` Then we'd replace _both_ of the original `foo` requirements with both of these overrides. (In technical terms, for each package in the requirements file, we flat-map over its overrides.) Closes https://github.com/astral-sh/puffin/issues/511.
45 lines
1.4 KiB
Rust
45 lines
1.4 KiB
Rust
use itertools::Either;
|
|
use std::hash::BuildHasherDefault;
|
|
|
|
use rustc_hash::FxHashMap;
|
|
|
|
use pep508_rs::Requirement;
|
|
use puffin_normalize::PackageName;
|
|
|
|
/// A set of overrides for a set of requirements.
|
|
#[derive(Debug, Default, Clone)]
|
|
pub(crate) struct Overrides(FxHashMap<PackageName, Vec<Requirement>>);
|
|
|
|
impl Overrides {
|
|
/// Create a new set of overrides from a set of requirements.
|
|
pub(crate) fn from_requirements(requirements: Vec<Requirement>) -> Self {
|
|
let mut overrides: FxHashMap<PackageName, Vec<Requirement>> =
|
|
FxHashMap::with_capacity_and_hasher(requirements.len(), BuildHasherDefault::default());
|
|
for requirement in requirements {
|
|
overrides
|
|
.entry(requirement.name.clone())
|
|
.or_default()
|
|
.push(requirement);
|
|
}
|
|
Self(overrides)
|
|
}
|
|
|
|
/// Get the overrides for a package.
|
|
pub(crate) fn get(&self, name: &PackageName) -> Option<&Vec<Requirement>> {
|
|
self.0.get(name)
|
|
}
|
|
|
|
/// Apply the overrides to a set of requirements.
|
|
pub(crate) fn apply<'a>(
|
|
&'a self,
|
|
requirements: &'a [Requirement],
|
|
) -> impl Iterator<Item = &Requirement> {
|
|
requirements.iter().flat_map(|requirement| {
|
|
if let Some(overrides) = self.get(&requirement.name) {
|
|
Either::Left(overrides.iter())
|
|
} else {
|
|
Either::Right(std::iter::once(requirement))
|
|
}
|
|
})
|
|
}
|
|
}
|