mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-27 10:26:29 +00:00
Treat --upgrade-package on the command-line as overriding upgrade = false in configuration (#15395)
## Summary Right now, if you put `upgrade = false` in a `uv.toml`, then pass `--upgrade-package numpy` on the CLI, we won't upgrade NumPy. This PR fixes that interaction by ensuring that when we "combine", we look at those arguments holistically (i.e., we bundle `upgrade` and `upgrade-package` into a single struct, which then goes through the `.combine` logic), rather than combining `upgrade` and `upgrade-package` independently. If approved, I then need to add the same thing for `no-build-isolation`, `reinstall`, `no-build`, and `no-binary`.
This commit is contained in:
parent
b950453891
commit
0397595e53
8 changed files with 357 additions and 145 deletions
|
|
@ -134,9 +134,57 @@ impl From<Reinstall> for Refresh {
|
|||
}
|
||||
}
|
||||
|
||||
/// An upgrade selection as specified by a user on the command line or in a configuration file.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub enum UpgradeSelection {
|
||||
/// Prefer pinned versions from the existing lockfile, if possible.
|
||||
#[default]
|
||||
None,
|
||||
|
||||
/// Allow package upgrades for all packages, ignoring the existing lockfile.
|
||||
All,
|
||||
|
||||
/// Allow package upgrades, but only for the specified packages.
|
||||
Packages(Vec<Requirement>),
|
||||
}
|
||||
|
||||
impl UpgradeSelection {
|
||||
/// Determine the upgrade selection strategy from the command-line arguments.
|
||||
pub fn from_args(upgrade: Option<bool>, upgrade_package: Vec<Requirement>) -> Option<Self> {
|
||||
match upgrade {
|
||||
Some(true) => Some(Self::All),
|
||||
// TODO(charlie): `--no-upgrade` with `--upgrade-package` should allow the specified
|
||||
// packages to be upgraded. Right now, `--upgrade-package` is silently ignored.
|
||||
Some(false) => Some(Self::None),
|
||||
None if upgrade_package.is_empty() => None,
|
||||
None => Some(Self::Packages(upgrade_package)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Combine a set of [`UpgradeSelection`] values.
|
||||
#[must_use]
|
||||
pub fn combine(self, other: Self) -> Self {
|
||||
match self {
|
||||
// Setting `--upgrade` or `--no-upgrade` should clear previous `--upgrade-package` selections.
|
||||
Self::All | Self::None => self,
|
||||
Self::Packages(self_packages) => match other {
|
||||
// If `--upgrade` was enabled previously, `--upgrade-package` is subsumed by upgrading all packages.
|
||||
Self::All => other,
|
||||
// If `--no-upgrade` was enabled previously, then `--upgrade-package` enables an explicit upgrade of those packages.
|
||||
Self::None => Self::Packages(self_packages),
|
||||
// If `--upgrade-package` was included twice, combine the requirements.
|
||||
Self::Packages(other_packages) => {
|
||||
let mut combined = self_packages;
|
||||
combined.extend(other_packages);
|
||||
Self::Packages(combined)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to allow package upgrades.
|
||||
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub enum Upgrade {
|
||||
/// Prefer pinned versions from the existing lockfile, if possible.
|
||||
#[default]
|
||||
|
|
@ -149,30 +197,28 @@ pub enum Upgrade {
|
|||
Packages(FxHashMap<PackageName, Vec<Requirement>>),
|
||||
}
|
||||
|
||||
impl Upgrade {
|
||||
/// Determine the [`Upgrade`] strategy from the command-line arguments.
|
||||
pub fn from_args(upgrade: Option<bool>, upgrade_package: Vec<Requirement>) -> Self {
|
||||
match upgrade {
|
||||
Some(true) => Self::All,
|
||||
Some(false) => Self::None,
|
||||
None => {
|
||||
if upgrade_package.is_empty() {
|
||||
Self::None
|
||||
} else {
|
||||
Self::Packages(upgrade_package.into_iter().fold(
|
||||
FxHashMap::default(),
|
||||
|mut map, requirement| {
|
||||
map.entry(requirement.name.clone())
|
||||
.or_default()
|
||||
.push(requirement);
|
||||
map
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
/// Determine the [`Upgrade`] strategy from the command-line arguments.
|
||||
impl From<Option<UpgradeSelection>> for Upgrade {
|
||||
fn from(value: Option<UpgradeSelection>) -> Self {
|
||||
match value {
|
||||
None => Self::None,
|
||||
Some(UpgradeSelection::None) => Self::None,
|
||||
Some(UpgradeSelection::All) => Self::All,
|
||||
Some(UpgradeSelection::Packages(requirements)) => Self::Packages(
|
||||
requirements
|
||||
.into_iter()
|
||||
.fold(FxHashMap::default(), |mut map, requirement| {
|
||||
map.entry(requirement.name.clone())
|
||||
.or_default()
|
||||
.push(requirement);
|
||||
map
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Upgrade {
|
||||
/// Create an [`Upgrade`] strategy to upgrade a single package.
|
||||
pub fn package(package_name: PackageName) -> Self {
|
||||
Self::Packages({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue