Add file-to-CLI overrides for reinstall configuration (#15426)

## Summary

This is like #15395, but for `--reinstall` and `--reinstall-package`.
This commit is contained in:
Charlie Marsh 2025-08-21 20:03:03 +01:00 committed by GitHub
parent ede75fe628
commit 330b54b173
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 51 additions and 52 deletions

View File

@ -1,7 +1,7 @@
use anstream::eprintln; use anstream::eprintln;
use uv_cache::Refresh; use uv_cache::Refresh;
use uv_configuration::Upgrade; use uv_configuration::{Reinstall, Upgrade};
use uv_distribution_types::{ConfigSettings, PackageConfigSettings, Requirement}; use uv_distribution_types::{ConfigSettings, PackageConfigSettings, Requirement};
use uv_resolver::{ExcludeNewer, ExcludeNewerPackage, PrereleaseMode}; use uv_resolver::{ExcludeNewer, ExcludeNewerPackage, PrereleaseMode};
use uv_settings::{Combine, PipOptions, ResolverInstallerOptions, ResolverOptions}; use uv_settings::{Combine, PipOptions, ResolverInstallerOptions, ResolverOptions};
@ -449,12 +449,10 @@ pub fn resolver_installer_options(
flag(upgrade, no_upgrade, "upgrade"), flag(upgrade, no_upgrade, "upgrade"),
upgrade_package.into_iter().map(Requirement::from).collect(), upgrade_package.into_iter().map(Requirement::from).collect(),
), ),
reinstall: flag(reinstall, no_reinstall, "reinstall"), reinstall: Reinstall::from_args(
reinstall_package: if reinstall_package.is_empty() { flag(reinstall, no_reinstall, "reinstall"),
None reinstall_package,
} else { ),
Some(reinstall_package)
},
index_strategy, index_strategy,
keyring_provider, keyring_provider,
resolution, resolution,

View File

@ -25,17 +25,12 @@ pub enum Reinstall {
impl Reinstall { impl Reinstall {
/// Determine the reinstall strategy to use. /// Determine the reinstall strategy to use.
pub fn from_args(reinstall: Option<bool>, reinstall_package: Vec<PackageName>) -> Self { pub fn from_args(reinstall: Option<bool>, reinstall_package: Vec<PackageName>) -> Option<Self> {
match reinstall { match reinstall {
Some(true) => Self::All, Some(true) => Some(Self::All),
Some(false) => Self::None, Some(false) => Some(Self::None),
None => { None if reinstall_package.is_empty() => None,
if reinstall_package.is_empty() { None => Some(Self::Packages(reinstall_package, Vec::new())),
Self::None
} else {
Self::Packages(reinstall_package, Vec::new())
}
}
} }
} }
@ -72,20 +67,23 @@ impl Reinstall {
/// Combine a set of [`Reinstall`] values. /// Combine a set of [`Reinstall`] values.
#[must_use] #[must_use]
pub fn combine(self, other: Self) -> Self { pub fn combine(self, other: Self) -> Self {
match (self, other) { match self {
// If both are `None`, the result is `None`. // Setting `--reinstall` or `--no-reinstall` should clear previous `--reinstall-package` selections.
(Self::None, Self::None) => Self::None, Self::All | Self::None => self,
// If either is `All`, the result is `All`. Self::Packages(self_packages, self_paths) => match other {
(Self::All, _) | (_, Self::All) => Self::All, // If `--reinstall` was enabled previously, `--reinstall-package` is subsumed by reinstalling all packages.
// If one is `None`, the result is the other. Self::All => other,
(Self::Packages(a1, a2), Self::None) => Self::Packages(a1, a2), // If `--no-reinstall` was enabled previously, then `--reinstall-package` enables an explicit reinstall of those packages.
(Self::None, Self::Packages(b1, b2)) => Self::Packages(b1, b2), Self::None => Self::Packages(self_packages, self_paths),
// If both are `Packages`, the result is the union of the two. // If `--reinstall-package` was included twice, combine the requirements.
(Self::Packages(mut a1, mut a2), Self::Packages(b1, b2)) => { Self::Packages(other_packages, other_paths) => {
a1.extend(b1); let mut combined_packages = self_packages;
a2.extend(b2); combined_packages.extend(other_packages);
Self::Packages(a1, a2) let mut combined_paths = self_paths;
combined_paths.extend(other_paths);
Self::Packages(combined_packages, combined_paths)
} }
},
} }
} }

View File

@ -4,7 +4,7 @@ use std::{collections::BTreeMap, num::NonZeroUsize};
use url::Url; use url::Url;
use uv_configuration::{ use uv_configuration::{
ExportFormat, IndexStrategy, KeyringProviderType, RequiredVersion, TargetTriple, ExportFormat, IndexStrategy, KeyringProviderType, Reinstall, RequiredVersion, TargetTriple,
TrustedPublishing, Upgrade, TrustedPublishing, Upgrade,
}; };
use uv_distribution_types::{ use uv_distribution_types::{
@ -190,6 +190,15 @@ impl Combine for Option<Upgrade> {
} }
} }
impl Combine for Option<Reinstall> {
fn combine(self, other: Self) -> Self {
match (self, other) {
(Some(a), Some(b)) => Some(a.combine(b)),
(a, b) => a.or(b),
}
}
}
impl Combine for serde::de::IgnoredAny { impl Combine for serde::de::IgnoredAny {
fn combine(self, _other: Self) -> Self { fn combine(self, _other: Self) -> Self {
self self

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
use uv_cache_info::CacheKey; use uv_cache_info::CacheKey;
use uv_configuration::{ use uv_configuration::{
IndexStrategy, KeyringProviderType, PackageNameSpecifier, RequiredVersion, TargetTriple, IndexStrategy, KeyringProviderType, PackageNameSpecifier, Reinstall, RequiredVersion,
TrustedHost, TrustedPublishing, Upgrade, TargetTriple, TrustedHost, TrustedPublishing, Upgrade,
}; };
use uv_distribution_types::{ use uv_distribution_types::{
ConfigSettings, ExtraBuildVariables, Index, IndexUrl, IndexUrlError, PackageConfigSettings, ConfigSettings, ExtraBuildVariables, Index, IndexUrl, IndexUrlError, PackageConfigSettings,
@ -408,8 +408,7 @@ pub struct ResolverInstallerOptions {
pub compile_bytecode: Option<bool>, pub compile_bytecode: Option<bool>,
pub no_sources: Option<bool>, pub no_sources: Option<bool>,
pub upgrade: Option<Upgrade>, pub upgrade: Option<Upgrade>,
pub reinstall: Option<bool>, pub reinstall: Option<Reinstall>,
pub reinstall_package: Option<Vec<PackageName>>,
pub no_build: Option<bool>, pub no_build: Option<bool>,
pub no_build_package: Option<Vec<PackageName>>, pub no_build_package: Option<Vec<PackageName>>,
pub no_binary: Option<bool>, pub no_binary: Option<bool>,
@ -481,8 +480,7 @@ impl From<ResolverInstallerSchema> for ResolverInstallerOptions {
.map(Into::into) .map(Into::into)
.collect(), .collect(),
), ),
reinstall, reinstall: Reinstall::from_args(reinstall, reinstall_package.unwrap_or_default()),
reinstall_package,
no_build, no_build,
no_build_package, no_build_package,
no_binary, no_binary,
@ -2041,7 +2039,6 @@ impl From<ToolOptions> for ResolverInstallerOptions {
no_sources: value.no_sources, no_sources: value.no_sources,
upgrade: None, upgrade: None,
reinstall: None, reinstall: None,
reinstall_package: None,
no_build: value.no_build, no_build: value.no_build,
no_build_package: value.no_build_package, no_build_package: value.no_build_package,
no_binary: value.no_binary, no_binary: value.no_binary,

View File

@ -246,9 +246,7 @@ pub(crate) async fn install(
// If the user passed `--force`, it implies `--reinstall-package <from>` // If the user passed `--force`, it implies `--reinstall-package <from>`
let settings = if force { let settings = if force {
ResolverInstallerSettings { ResolverInstallerSettings {
reinstall: settings reinstall: Reinstall::package(package_name.clone()).combine(settings.reinstall),
.reinstall
.combine(Reinstall::package(package_name.clone())),
..settings ..settings
} }
} else { } else {

View File

@ -2946,10 +2946,7 @@ impl From<ResolverInstallerOptions> for ResolverInstallerSettings {
upgrade: value.upgrade.unwrap_or_default(), upgrade: value.upgrade.unwrap_or_default(),
}, },
compile_bytecode: value.compile_bytecode.unwrap_or_default(), compile_bytecode: value.compile_bytecode.unwrap_or_default(),
reinstall: Reinstall::from_args( reinstall: value.reinstall.unwrap_or_default(),
value.reinstall,
value.reinstall_package.unwrap_or_default(),
),
} }
} }
} }
@ -3335,11 +3332,14 @@ impl PipSettings {
)) ))
.unwrap_or_default(), .unwrap_or_default(),
reinstall: Reinstall::from_args( reinstall: Reinstall::from_args(
args.reinstall.combine(reinstall), args.reinstall,
args.reinstall_package args.reinstall_package.unwrap_or_default(),
.combine(reinstall_package) )
.combine(Reinstall::from_args(
reinstall,
reinstall_package.unwrap_or_default(),
))
.unwrap_or_default(), .unwrap_or_default(),
),
build_options: BuildOptions::new( build_options: BuildOptions::new(
NoBinary::from_pip_args(args.no_binary.combine(no_binary).unwrap_or_default()) NoBinary::from_pip_args(args.no_binary.combine(no_binary).unwrap_or_default())
.combine(NoBinary::from_args( .combine(NoBinary::from_args(

View File

@ -3515,7 +3515,6 @@ fn resolve_tool() -> anyhow::Result<()> {
no_sources: None, no_sources: None,
upgrade: None, upgrade: None,
reinstall: None, reinstall: None,
reinstall_package: None,
no_build: None, no_build: None,
no_build_package: None, no_build_package: None,
no_binary: None, no_binary: None,