remove --allow-decreases and be extremely strict about args

This commit is contained in:
Aria Desires 2025-05-22 12:58:32 -04:00
parent 2fddfa7088
commit fb525a6ed4
6 changed files with 104 additions and 19 deletions

View file

@ -535,10 +535,8 @@ pub struct VersionArgs {
/// Update the project version using the given semantics
///
/// This flag can be passed multiple times, and the bumps will be applied in the
/// following order that prevents bumps from being undone by other bumps:
///
/// major > minor > patch > stable > alpha > beta > rc > post > dev
/// This flag can be passed multiple times to allow going to a new release and entering
/// a prerelease: `--bump patch --bump beta`
#[arg(group = "operation", long)]
pub bump: Vec<VersionBump>,
@ -554,10 +552,6 @@ pub struct VersionArgs {
#[arg(long)]
pub short: bool,
/// Permit the result of `--bump` to be a version decrease
#[arg(long)]
pub allow_decreases: bool,
/// The format of the output
#[arg(long, value_enum, default_value = "text")]
pub output_format: VersionFormat,
@ -645,6 +639,23 @@ pub enum VersionBump {
Dev,
}
impl std::fmt::Display for VersionBump {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let string = match self {
VersionBump::Major => "major",
VersionBump::Minor => "minor",
VersionBump::Patch => "patch",
VersionBump::Stable => "stable",
VersionBump::Alpha => "alpha",
VersionBump::Beta => "beta",
VersionBump::Rc => "rc",
VersionBump::Post => "post",
VersionBump::Dev => "dev",
};
string.fmt(f)
}
}
#[derive(Args)]
pub struct SelfNamespace {
#[command(subcommand)]

View file

@ -59,7 +59,6 @@ pub(crate) async fn project_version(
short: bool,
output_format: VersionFormat,
strict: bool,
allow_decreases: bool,
project_dir: &Path,
package: Option<PackageName>,
dry_run: bool,
@ -171,8 +170,82 @@ pub(crate) async fn project_version(
},
}
} else if !bump.is_empty() {
// While we can rationalize many of these combinations of operations together,
// we want to conservatively refuse to support any of them until users demand it.
//
// The most complex thing we *do* allow is `--bump major --bump beta --bump dev`
// because that makes perfect sense and is reasonable to do.
let release_components: Vec<_> = bump
.iter()
.filter(|bump| {
matches!(
bump,
VersionBump::Major | VersionBump::Minor | VersionBump::Patch
)
})
.collect();
let prerelease_components: Vec<_> = bump
.iter()
.filter(|bump| {
matches!(
bump,
VersionBump::Alpha | VersionBump::Beta | VersionBump::Rc | VersionBump::Dev
)
})
.collect();
let post_count = bump
.iter()
.filter(|bump| *bump == &VersionBump::Post)
.count();
let stable_count = bump
.iter()
.filter(|bump| *bump == &VersionBump::Stable)
.count();
// Very little reason to do "bump to stable" and then do other things,
// even if we can make sense of it.
if stable_count > 0 && bump.len() > 1 {
if let Some(component) = release_components.first() {
return Err(anyhow!(
"`--bump stable` isn't needed if you're already passing `--bump {component}`"
));
}
return Err(anyhow!(
"`--bump stable` cannot be combined with any other `--bump`"
));
}
// Very little reason to "bump to post" and then do other things,
// how is it a post-release otherwise?
if post_count > 0 && bump.len() > 1 {
return Err(anyhow!(
"`--bump post` cannot be combined with any other `--bump`"
));
}
// `--bump major --bump minor` makes perfect sense (1.2.3 => 2.1.0)
// ...but it's weird and probably a mistake?
// `--bump major --bump major` perfect sense (1.2.3 => 3.0.0)
// ...but it's weird and probably a mistake?
if release_components.len() > 1 {
return Err(anyhow!(
"`--bump` can only take one of `major`, `minor`, `patch`"
));
}
// `--bump alpha --bump beta` is basically completely incoherent
// `--bump beta --bump beta` makes perfect sense (1.2.3b4 => 1.2.3b6)
// ...but it's weird and probably a mistake?
// `--bump beta --bump dev` makes perfect sense (1.2.3 => 1.2.3b1.dev1)
// ...but we want to discourage mixing `dev` with prereleases
if prerelease_components.len() > 1 {
return Err(anyhow!(
"`--bump` can only take one of `alpha`, `beta`, `rc`, `dev`"
));
}
// Sort the given commands so the user doesn't have to care about
// the ordering of `--bump minor --bump major` (only one ordering is ever useful)
// the ordering of `--bump minor --bump beta` (only one ordering is ever useful)
bump.sort();
// Apply all the bumps
@ -198,9 +271,14 @@ pub(crate) async fn project_version(
new_version.bump(command);
}
if !allow_decreases && new_version < old_version {
if new_version <= old_version {
if old_version.is_stable() && new_version.is_pre() {
return Err(anyhow!(
"{old_version} => {new_version} didn't increase the version; when moving to a prerelease you also need to increase the release `--bump patch`?"
));
}
return Err(anyhow!(
"{old_version} => {new_version} was a version decrease, use `--allow-decreases` if this is desired"
"{old_version} => {new_version} didn't increase the version"
));
}

View file

@ -1989,7 +1989,6 @@ async fn run_project(
args.short,
args.output_format,
strict,
args.allow_decreases,
project_dir,
args.package,
args.dry_run,

View file

@ -1495,7 +1495,6 @@ pub(crate) struct VersionSettings {
pub(crate) value: Option<String>,
pub(crate) bump: Vec<VersionBump>,
pub(crate) short: bool,
pub(crate) allow_decreases: bool,
pub(crate) output_format: VersionFormat,
pub(crate) dry_run: bool,
pub(crate) locked: bool,
@ -1517,7 +1516,6 @@ impl VersionSettings {
value,
bump,
short,
allow_decreases,
output_format,
dry_run,
no_sync,
@ -1541,7 +1539,6 @@ impl VersionSettings {
value,
bump,
short,
allow_decreases,
output_format,
dry_run,
locked,

View file

@ -160,6 +160,8 @@ Setting `tool.uv.package = false` will force a project package _not_ to be built
the project environment. uv will ignore a declared build system when interacting with the project;
however, uv will still respect explicit attempts to build the project such as invoking `uv build`.
## Project versioning
## Project environment path
The `UV_PROJECT_ENVIRONMENT` environment variable can be used to configure the project virtual

View file

@ -769,14 +769,12 @@ uv version [OPTIONS] [VALUE]
<dl class="cli-reference"><dt id="uv-version--active"><a href="#uv-version--active"><code>--active</code></a></dt><dd><p>Prefer the active virtual environment over the project's virtual environment.</p>
<p>If the project virtual environment is active or no virtual environment is active, this has no effect.</p>
</dd><dt id="uv-version--allow-decreases"><a href="#uv-version--allow-decreases"><code>--allow-decreases</code></a></dt><dd><p>Permit the result of <code>--bump</code> to be a version decrease</p>
</dd><dt id="uv-version--allow-insecure-host"><a href="#uv-version--allow-insecure-host"><code>--allow-insecure-host</code></a>, <code>--trusted-host</code> <i>allow-insecure-host</i></dt><dd><p>Allow insecure connections to a host.</p>
<p>Can be provided multiple times.</p>
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
<p>WARNING: Hosts included in this list will not be verified against the system's certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
<p>May also be set with the <code>UV_INSECURE_HOST</code> environment variable.</p></dd><dt id="uv-version--bump"><a href="#uv-version--bump"><code>--bump</code></a> <i>bump</i></dt><dd><p>Update the project version using the given semantics</p>
<p>This flag can be passed multiple times, and the bumps will be applied in the following order that prevents bumps from being undone by other bumps:</p>
<p>major &gt; minor &gt; patch &gt; stable &gt; alpha &gt; beta &gt; rc &gt; post &gt; dev</p>
<p>This flag can be passed multiple times to allow going to a new release and entering a prerelease: <code>--bump patch --bump beta</code></p>
<p>Possible values:</p>
<ul>
<li><code>major</code>: Increase the major version (1.2.3 =&gt; 2.0.0)</li>