Apply --no-install options when constructing resolution (#7277)

## Summary

We need to apply the `--no-install` filters earlier, such that we don't
error if we only have a source distribution for a given package when
`--no-build` is provided but that package is _omitted_.

Closes #7247.
This commit is contained in:
Charlie Marsh 2024-09-11 14:31:24 -04:00 committed by GitHub
parent 7021b15a42
commit 15792a3775
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 114 additions and 82 deletions

View file

@ -1,15 +1,16 @@
use std::collections::BTreeSet;
use rustc_hash::FxHashSet;
use tracing::debug;
use distribution_types::{Name, Resolution};
use pep508_rs::PackageName;
#[derive(Debug, Clone, Default)]
pub struct InstallOptions {
/// Omit the project itself from the resolution.
pub no_install_project: bool,
/// Omit all workspace members (including the project itself) from the resolution.
pub no_install_workspace: bool,
/// Omit the specified packages from the resolution.
pub no_install_package: Vec<PackageName>,
}
@ -26,81 +27,48 @@ impl InstallOptions {
}
}
pub fn filter_resolution(
&self,
resolution: Resolution,
project_name: Option<&PackageName>,
members: &BTreeSet<PackageName>,
) -> Resolution {
// If `--no-install-project` is set, remove the project itself.
let resolution = self.apply_no_install_project(resolution, project_name);
// If `--no-install-workspace` is set, remove the project and any workspace members.
let resolution = self.apply_no_install_workspace(resolution, members);
// If `--no-install-package` is provided, remove the requested packages.
self.apply_no_install_package(resolution)
}
fn apply_no_install_project(
&self,
resolution: Resolution,
project_name: Option<&PackageName>,
) -> Resolution {
if !self.no_install_project {
return resolution;
}
let Some(project_name) = project_name else {
debug!("Ignoring `--no-install-project` for virtual workspace");
return resolution;
};
resolution.filter(|dist| dist.name() != project_name)
}
fn apply_no_install_workspace(
&self,
resolution: Resolution,
members: &BTreeSet<PackageName>,
) -> Resolution {
if !self.no_install_workspace {
return resolution;
}
resolution.filter(|dist| !members.contains(dist.name()))
}
fn apply_no_install_package(&self, resolution: Resolution) -> Resolution {
if self.no_install_package.is_empty() {
return resolution;
}
let no_install_packages = self.no_install_package.iter().collect::<FxHashSet<_>>();
resolution.filter(|dist| !no_install_packages.contains(dist.name()))
}
/// Returns `true` if a package passes the install filters.
pub fn include_package(
&self,
package: &PackageName,
project_name: &PackageName,
project_name: Option<&PackageName>,
members: &BTreeSet<PackageName>,
) -> bool {
// If `--no-install-project` is set, remove the project itself. The project is always
// part of the workspace.
if (self.no_install_project || self.no_install_workspace) && package == project_name {
return false;
// If `--no-install-project` is set, remove the project itself.
if self.no_install_project {
if let Some(project_name) = project_name {
if package == project_name {
debug!("Omitting `{package}` from resolution due to `--no-install-project`");
return false;
}
}
}
// If `--no-install-workspace` is set, remove the project and any workspace members.
if self.no_install_workspace && members.contains(package) {
return false;
if self.no_install_workspace {
// In some cases, the project root might be omitted from the list of workspace members
// encoded in the lockfile. (But we already checked this above if `--no-install-project`
// is set.)
if !self.no_install_project {
if let Some(project_name) = project_name {
if package == project_name {
debug!(
"Omitting `{package}` from resolution due to `--no-install-workspace`"
);
return false;
}
}
}
if members.contains(package) {
debug!("Omitting `{package}` from resolution due to `--no-install-workspace`");
return false;
}
}
// If `--no-install-package` is provided, remove the requested packages.
if self.no_install_package.contains(package) {
debug!("Omitting `{package}` from resolution due to `--no-install-package`");
return false;
}