mirror of https://github.com/astral-sh/uv
Allow explicit values with `uv version --bump` (#16555)
Resolves https://github.com/astral-sh/uv/issues/16427 This PR updates `uv version --bump` so you can pin the exact number you’re targeting, i.e. `--bump patch=10` or `--bump dev=42`. The command-line interface now parses those `component=value` flags, and the bump logic actually sets the version to the number you asked for.
This commit is contained in:
parent
3ccad58166
commit
63ab247765
|
|
@ -1,11 +1,14 @@
|
|||
use std::ffi::OsString;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use clap::builder::Styles;
|
||||
use clap::ValueEnum;
|
||||
use clap::builder::styling::{AnsiColor, Effects, Style};
|
||||
use clap::builder::{PossibleValue, Styles, TypedValueParser, ValueParserFactory};
|
||||
use clap::error::ErrorKind;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
use uv_auth::Service;
|
||||
|
|
@ -587,8 +590,8 @@ pub struct VersionArgs {
|
|||
/// Update the project version using the given semantics
|
||||
///
|
||||
/// This flag can be passed multiple times.
|
||||
#[arg(group = "operation", long)]
|
||||
pub bump: Vec<VersionBump>,
|
||||
#[arg(group = "operation", long, value_name = "BUMP[=VALUE]")]
|
||||
pub bump: Vec<VersionBumpSpec>,
|
||||
|
||||
/// Don't write a new version to the `pyproject.toml`
|
||||
///
|
||||
|
|
@ -698,8 +701,8 @@ pub enum VersionBump {
|
|||
Dev,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for VersionBump {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl Display for VersionBump {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let string = match self {
|
||||
Self::Major => "major",
|
||||
Self::Minor => "minor",
|
||||
|
|
@ -715,6 +718,110 @@ impl std::fmt::Display for VersionBump {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromStr for VersionBump {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"major" => Ok(Self::Major),
|
||||
"minor" => Ok(Self::Minor),
|
||||
"patch" => Ok(Self::Patch),
|
||||
"stable" => Ok(Self::Stable),
|
||||
"alpha" => Ok(Self::Alpha),
|
||||
"beta" => Ok(Self::Beta),
|
||||
"rc" => Ok(Self::Rc),
|
||||
"post" => Ok(Self::Post),
|
||||
"dev" => Ok(Self::Dev),
|
||||
_ => Err(format!("invalid bump component `{value}`")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct VersionBumpSpec {
|
||||
pub bump: VersionBump,
|
||||
pub value: Option<u64>,
|
||||
}
|
||||
|
||||
impl Display for VersionBumpSpec {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self.value {
|
||||
Some(value) => write!(f, "{}={value}", self.bump),
|
||||
None => self.bump.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for VersionBumpSpec {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
let (name, value) = match input.split_once('=') {
|
||||
Some((name, value)) => (name, Some(value)),
|
||||
None => (input, None),
|
||||
};
|
||||
|
||||
let bump = name.parse::<VersionBump>()?;
|
||||
|
||||
if bump == VersionBump::Stable && value.is_some() {
|
||||
return Err("`--bump stable` does not accept a value".to_string());
|
||||
}
|
||||
|
||||
let value = match value {
|
||||
Some("") => {
|
||||
return Err("`--bump` values cannot be empty".to_string());
|
||||
}
|
||||
Some(raw) => Some(
|
||||
raw.parse::<u64>()
|
||||
.map_err(|_| format!("invalid numeric value `{raw}` for `--bump {name}`"))?,
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok(Self { bump, value })
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueParserFactory for VersionBumpSpec {
|
||||
type Parser = VersionBumpSpecValueParser;
|
||||
|
||||
fn value_parser() -> Self::Parser {
|
||||
VersionBumpSpecValueParser
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VersionBumpSpecValueParser;
|
||||
|
||||
impl TypedValueParser for VersionBumpSpecValueParser {
|
||||
type Value = VersionBumpSpec;
|
||||
|
||||
fn parse_ref(
|
||||
&self,
|
||||
_cmd: &clap::Command,
|
||||
_arg: Option<&clap::Arg>,
|
||||
value: &std::ffi::OsStr,
|
||||
) -> Result<Self::Value, clap::Error> {
|
||||
let raw = value.to_str().ok_or_else(|| {
|
||||
clap::Error::raw(
|
||||
ErrorKind::InvalidUtf8,
|
||||
"`--bump` values must be valid UTF-8",
|
||||
)
|
||||
})?;
|
||||
|
||||
VersionBumpSpec::from_str(raw)
|
||||
.map_err(|message| clap::Error::raw(ErrorKind::InvalidValue, message))
|
||||
}
|
||||
|
||||
fn possible_values(&self) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>> {
|
||||
Some(Box::new(
|
||||
VersionBump::value_variants()
|
||||
.iter()
|
||||
.filter_map(ValueEnum::to_possible_value),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct SelfNamespace {
|
||||
#[command(subcommand)]
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ impl Version {
|
|||
let full = self.make_full();
|
||||
|
||||
match bump {
|
||||
BumpCommand::BumpRelease { index } => {
|
||||
BumpCommand::BumpRelease { index, value } => {
|
||||
// Clear all sub-release items
|
||||
full.pre = None;
|
||||
full.post = None;
|
||||
|
|
@ -690,7 +690,9 @@ impl Version {
|
|||
// Everything before the bumped value is preserved (or is an implicit 0)
|
||||
Ordering::Less => old_parts.get(i).copied().unwrap_or(0),
|
||||
// This is the value to bump (could be implicit 0)
|
||||
Ordering::Equal => old_parts.get(i).copied().unwrap_or(0) + 1,
|
||||
Ordering::Equal => {
|
||||
value.unwrap_or_else(|| old_parts.get(i).copied().unwrap_or(0) + 1)
|
||||
}
|
||||
// Everything after the bumped value becomes 0
|
||||
Ordering::Greater => 0,
|
||||
})
|
||||
|
|
@ -703,37 +705,50 @@ impl Version {
|
|||
full.post = None;
|
||||
full.dev = None;
|
||||
}
|
||||
BumpCommand::BumpPrerelease { kind } => {
|
||||
BumpCommand::BumpPrerelease { kind, value } => {
|
||||
// Clear all sub-prerelease items
|
||||
full.post = None;
|
||||
full.dev = None;
|
||||
|
||||
// Either bump the matching kind or set to 1
|
||||
if let Some(prerelease) = &mut full.pre {
|
||||
if prerelease.kind == kind {
|
||||
prerelease.number += 1;
|
||||
return;
|
||||
if let Some(value) = value {
|
||||
full.pre = Some(Prerelease {
|
||||
kind,
|
||||
number: value,
|
||||
});
|
||||
} else {
|
||||
// Either bump the matching kind or set to 1
|
||||
if let Some(prerelease) = &mut full.pre {
|
||||
if prerelease.kind == kind {
|
||||
prerelease.number += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
full.pre = Some(Prerelease { kind, number: 1 });
|
||||
}
|
||||
full.pre = Some(Prerelease { kind, number: 1 });
|
||||
}
|
||||
BumpCommand::BumpPost => {
|
||||
BumpCommand::BumpPost { value } => {
|
||||
// Clear sub-post items
|
||||
full.dev = None;
|
||||
|
||||
// Either bump or set to 1
|
||||
if let Some(post) = &mut full.post {
|
||||
*post += 1;
|
||||
if let Some(value) = value {
|
||||
full.post = Some(value);
|
||||
} else {
|
||||
full.post = Some(1);
|
||||
// Either bump or set to 1
|
||||
if let Some(post) = &mut full.post {
|
||||
*post += 1;
|
||||
} else {
|
||||
full.post = Some(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
BumpCommand::BumpDev => {
|
||||
// Either bump or set to 1
|
||||
if let Some(dev) = &mut full.dev {
|
||||
*dev += 1;
|
||||
BumpCommand::BumpDev { value } => {
|
||||
if let Some(value) = value {
|
||||
full.dev = Some(value);
|
||||
} else {
|
||||
full.dev = Some(1);
|
||||
// Either bump or set to 1
|
||||
if let Some(dev) = &mut full.dev {
|
||||
*dev += 1;
|
||||
} else {
|
||||
full.dev = Some(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1018,22 +1033,32 @@ impl FromStr for Version {
|
|||
/// Various ways to "bump" a version
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum BumpCommand {
|
||||
/// Bump the release component
|
||||
/// Bump or set the release component
|
||||
BumpRelease {
|
||||
/// The release component to bump (0 is major, 1 is minor, 2 is patch)
|
||||
index: usize,
|
||||
/// Explicit value to set; when absent the component is incremented
|
||||
value: Option<u64>,
|
||||
},
|
||||
/// Bump the prerelease component
|
||||
/// Bump or set the prerelease component
|
||||
BumpPrerelease {
|
||||
/// prerelease component to bump
|
||||
kind: PrereleaseKind,
|
||||
/// Explicit value to set; when absent the component is incremented
|
||||
value: Option<u64>,
|
||||
},
|
||||
/// Bump to the associated stable release
|
||||
MakeStable,
|
||||
/// Bump the post component
|
||||
BumpPost,
|
||||
/// Bump the dev component
|
||||
BumpDev,
|
||||
/// Bump or set the post component
|
||||
BumpPost {
|
||||
/// Explicit value to set; when absent the component is incremented
|
||||
value: Option<u64>,
|
||||
},
|
||||
/// Bump or set the dev component
|
||||
BumpDev {
|
||||
/// Explicit value to set; when absent the component is incremented
|
||||
value: Option<u64>,
|
||||
},
|
||||
}
|
||||
|
||||
/// A small representation of a version.
|
||||
|
|
@ -4239,36 +4264,57 @@ mod tests {
|
|||
fn bump_major() {
|
||||
// one digit
|
||||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1");
|
||||
|
||||
// two digit
|
||||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "2.0");
|
||||
|
||||
// three digit (zero major)
|
||||
let mut version = "0.1.2".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.0.0");
|
||||
|
||||
// three digit (non-zero major)
|
||||
let mut version = "1.2.3".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "2.0.0");
|
||||
|
||||
// four digit
|
||||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "2.0.0.0");
|
||||
|
||||
// All the version junk
|
||||
let mut version = "5!1.7.3.5b2.post345.dev456+local"
|
||||
.parse::<Version>()
|
||||
.unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!2.0.0.0+local");
|
||||
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!3.0.0.0+local");
|
||||
}
|
||||
|
||||
|
|
@ -4278,31 +4324,49 @@ mod tests {
|
|||
fn bump_minor() {
|
||||
// one digit
|
||||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "0.1");
|
||||
|
||||
// two digit
|
||||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.6");
|
||||
|
||||
// three digit (non-zero major)
|
||||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5.4.0");
|
||||
|
||||
// four digit
|
||||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.3.0.0");
|
||||
|
||||
// All the version junk
|
||||
let mut version = "5!1.7.3.5b2.post345.dev456+local"
|
||||
.parse::<Version>()
|
||||
.unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.8.0.0+local");
|
||||
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.9.0.0+local");
|
||||
}
|
||||
|
||||
|
|
@ -4312,31 +4376,49 @@ mod tests {
|
|||
fn bump_patch() {
|
||||
// one digit
|
||||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "0.0.1");
|
||||
|
||||
// two digit
|
||||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.5.1");
|
||||
|
||||
// three digit
|
||||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5.3.7");
|
||||
|
||||
// four digit
|
||||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.2.4.0");
|
||||
|
||||
// All the version junk
|
||||
let mut version = "5!1.7.3.5b2.post345.dev456+local"
|
||||
.parse::<Version>()
|
||||
.unwrap();
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.4.0+local");
|
||||
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||
version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.5.0+local");
|
||||
}
|
||||
|
||||
|
|
@ -4348,6 +4430,7 @@ mod tests {
|
|||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "0a1");
|
||||
|
||||
|
|
@ -4355,6 +4438,7 @@ mod tests {
|
|||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.5a1");
|
||||
|
||||
|
|
@ -4362,6 +4446,7 @@ mod tests {
|
|||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5.3.6a1");
|
||||
|
||||
|
|
@ -4369,6 +4454,7 @@ mod tests {
|
|||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.2.3.4a1");
|
||||
|
||||
|
|
@ -4378,10 +4464,12 @@ mod tests {
|
|||
.unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5a1+local");
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5a2+local");
|
||||
}
|
||||
|
|
@ -4394,6 +4482,7 @@ mod tests {
|
|||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "0b1");
|
||||
|
||||
|
|
@ -4401,6 +4490,7 @@ mod tests {
|
|||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.5b1");
|
||||
|
||||
|
|
@ -4408,6 +4498,7 @@ mod tests {
|
|||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5.3.6b1");
|
||||
|
||||
|
|
@ -4415,6 +4506,7 @@ mod tests {
|
|||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.2.3.4b1");
|
||||
|
||||
|
|
@ -4424,10 +4516,12 @@ mod tests {
|
|||
.unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b1+local");
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2+local");
|
||||
}
|
||||
|
|
@ -4440,6 +4534,7 @@ mod tests {
|
|||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "0rc1");
|
||||
|
||||
|
|
@ -4447,6 +4542,7 @@ mod tests {
|
|||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.5rc1");
|
||||
|
||||
|
|
@ -4454,6 +4550,7 @@ mod tests {
|
|||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5.3.6rc1");
|
||||
|
||||
|
|
@ -4461,6 +4558,7 @@ mod tests {
|
|||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "1.2.3.4rc1");
|
||||
|
||||
|
|
@ -4470,10 +4568,12 @@ mod tests {
|
|||
.unwrap();
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc1+local");
|
||||
version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
value: None,
|
||||
});
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc2+local");
|
||||
}
|
||||
|
|
@ -4484,29 +4584,29 @@ mod tests {
|
|||
fn bump_post() {
|
||||
// one digit
|
||||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "0.post1");
|
||||
|
||||
// two digit
|
||||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "1.5.post1");
|
||||
|
||||
// three digit
|
||||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "5.3.6.post1");
|
||||
|
||||
// four digit
|
||||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "1.2.3.4.post1");
|
||||
|
||||
// All the version junk
|
||||
let mut version = "5!1.7.3.5b2.dev123+local".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post1+local");
|
||||
version.bump(BumpCommand::BumpPost);
|
||||
version.bump(BumpCommand::BumpPost { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post2+local");
|
||||
}
|
||||
|
||||
|
|
@ -4516,32 +4616,32 @@ mod tests {
|
|||
fn bump_dev() {
|
||||
// one digit
|
||||
let mut version = "0".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "0.dev1");
|
||||
|
||||
// two digit
|
||||
let mut version = "1.5".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "1.5.dev1");
|
||||
|
||||
// three digit
|
||||
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "5.3.6.dev1");
|
||||
|
||||
// four digit
|
||||
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(version.to_string().as_str(), "1.2.3.4.dev1");
|
||||
|
||||
// All the version junk
|
||||
let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(
|
||||
version.to_string().as_str(),
|
||||
"5!1.7.3.5b2.post345.dev1+local"
|
||||
);
|
||||
version.bump(BumpCommand::BumpDev);
|
||||
version.bump(BumpCommand::BumpDev { value: None });
|
||||
assert_eq!(
|
||||
version.to_string().as_str(),
|
||||
"5!1.7.3.5b2.post345.dev2+local"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use owo_colors::OwoColorize;
|
|||
use tracing::debug;
|
||||
use uv_cache::Cache;
|
||||
use uv_cli::version::VersionInfo;
|
||||
use uv_cli::{VersionBump, VersionFormat};
|
||||
use uv_cli::{VersionBump, VersionBumpSpec, VersionFormat};
|
||||
use uv_client::BaseClientBuilder;
|
||||
use uv_configuration::{
|
||||
Concurrency, DependencyGroups, DependencyGroupsWithDefaults, DryRun, ExtrasSpecification,
|
||||
|
|
@ -56,7 +56,7 @@ pub(crate) fn self_version(
|
|||
#[allow(clippy::fn_params_excessive_bools)]
|
||||
pub(crate) async fn project_version(
|
||||
value: Option<String>,
|
||||
mut bump: Vec<VersionBump>,
|
||||
mut bump: Vec<VersionBumpSpec>,
|
||||
short: bool,
|
||||
output_format: VersionFormat,
|
||||
project_dir: &Path,
|
||||
|
|
@ -164,29 +164,29 @@ pub(crate) async fn project_version(
|
|||
// because that makes perfect sense and is reasonable to do.
|
||||
let release_components: Vec<_> = bump
|
||||
.iter()
|
||||
.filter(|bump| {
|
||||
.filter(|spec| {
|
||||
matches!(
|
||||
bump,
|
||||
spec.bump,
|
||||
VersionBump::Major | VersionBump::Minor | VersionBump::Patch
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let prerelease_components: Vec<_> = bump
|
||||
.iter()
|
||||
.filter(|bump| {
|
||||
.filter(|spec| {
|
||||
matches!(
|
||||
bump,
|
||||
spec.bump,
|
||||
VersionBump::Alpha | VersionBump::Beta | VersionBump::Rc | VersionBump::Dev
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let post_count = bump
|
||||
.iter()
|
||||
.filter(|bump| *bump == &VersionBump::Post)
|
||||
.filter(|spec| spec.bump == VersionBump::Post)
|
||||
.count();
|
||||
let stable_count = bump
|
||||
.iter()
|
||||
.filter(|bump| *bump == &VersionBump::Stable)
|
||||
.filter(|spec| spec.bump == VersionBump::Stable)
|
||||
.count();
|
||||
|
||||
// Very little reason to do "bump to stable" and then do other things,
|
||||
|
|
@ -252,25 +252,37 @@ pub(crate) async fn project_version(
|
|||
|
||||
// Apply all the bumps
|
||||
let mut new_version = old_version.clone();
|
||||
for bump in &bump {
|
||||
let command = match *bump {
|
||||
VersionBump::Major => BumpCommand::BumpRelease { index: 0 },
|
||||
VersionBump::Minor => BumpCommand::BumpRelease { index: 1 },
|
||||
VersionBump::Patch => BumpCommand::BumpRelease { index: 2 },
|
||||
VersionBump::Alpha => BumpCommand::BumpPrerelease {
|
||||
|
||||
for spec in &bump {
|
||||
match spec.bump {
|
||||
VersionBump::Major => new_version.bump(BumpCommand::BumpRelease {
|
||||
index: 0,
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Minor => new_version.bump(BumpCommand::BumpRelease {
|
||||
index: 1,
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Patch => new_version.bump(BumpCommand::BumpRelease {
|
||||
index: 2,
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Stable => new_version.bump(BumpCommand::MakeStable),
|
||||
VersionBump::Alpha => new_version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Alpha,
|
||||
},
|
||||
VersionBump::Beta => BumpCommand::BumpPrerelease {
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Beta => new_version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Beta,
|
||||
},
|
||||
VersionBump::Rc => BumpCommand::BumpPrerelease {
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Rc => new_version.bump(BumpCommand::BumpPrerelease {
|
||||
kind: PrereleaseKind::Rc,
|
||||
},
|
||||
VersionBump::Post => BumpCommand::BumpPost,
|
||||
VersionBump::Dev => BumpCommand::BumpDev,
|
||||
VersionBump::Stable => BumpCommand::MakeStable,
|
||||
};
|
||||
new_version.bump(command);
|
||||
value: spec.value,
|
||||
}),
|
||||
VersionBump::Post => new_version.bump(BumpCommand::BumpPost { value: spec.value }),
|
||||
VersionBump::Dev => new_version.bump(BumpCommand::BumpDev { value: spec.value }),
|
||||
}
|
||||
}
|
||||
|
||||
if new_version <= old_version {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use uv_cli::{
|
|||
PythonFindArgs, PythonInstallArgs, PythonListArgs, PythonListFormat, PythonPinArgs,
|
||||
PythonUninstallArgs, PythonUpgradeArgs, RemoveArgs, RunArgs, SyncArgs, SyncFormat, ToolDirArgs,
|
||||
ToolInstallArgs, ToolListArgs, ToolRunArgs, ToolUninstallArgs, TreeArgs, VenvArgs, VersionArgs,
|
||||
VersionBump, VersionFormat,
|
||||
VersionBumpSpec, VersionFormat,
|
||||
};
|
||||
use uv_cli::{
|
||||
AuthorFrom, BuildArgs, ExportArgs, FormatArgs, PublishArgs, PythonDirArgs,
|
||||
|
|
@ -1792,7 +1792,7 @@ impl RemoveSettings {
|
|||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct VersionSettings {
|
||||
pub(crate) value: Option<String>,
|
||||
pub(crate) bump: Vec<VersionBump>,
|
||||
pub(crate) bump: Vec<VersionBumpSpec>,
|
||||
pub(crate) short: bool,
|
||||
pub(crate) output_format: VersionFormat,
|
||||
pub(crate) dry_run: bool,
|
||||
|
|
|
|||
|
|
@ -248,6 +248,123 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_bump_patch_value() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.10.31"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("patch=40"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 1.10.31 => 1.10.40
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.10.40"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_bump_minor_value() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("minor=10"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 1.2.3 => 1.10.0
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.10.0"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_bump_major_value() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "2.3.4"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("major=7"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 2.3.4 => 7.0.0
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "7.0.0"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Bump patch version (--short)
|
||||
#[test]
|
||||
fn version_bump_patch_short() -> Result<()> {
|
||||
|
|
@ -289,6 +406,43 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn version_bump_patch_value_must_increase() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.0.12"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("patch=11"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: 0.0.12 => 0.0.11 didn't increase the version; provide the exact version to force an update
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.0.12"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Preserve comments immediately preceding the version when bumping
|
||||
#[test]
|
||||
fn version_bump_preserves_preceding_comments() -> Result<()> {
|
||||
|
|
@ -781,6 +935,85 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_beta_with_value_existing() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3b4"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("beta=42"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 1.2.3b4 => 1.2.3b42
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3b42"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_beta_with_value_new() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("beta=5")
|
||||
.arg("--bump").arg("patch"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 1.2.3 => 1.2.4b5
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.4b5"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// --bump rc
|
||||
#[test]
|
||||
fn bump_rc() -> Result<()> {
|
||||
|
|
@ -861,6 +1094,45 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_post_with_value_clears_dev() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3.post4.dev9"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("post=10"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 1.2.3.post4.dev9 => 1.2.3.post10
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3.post10"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// --bump dev
|
||||
#[test]
|
||||
fn bump_dev() -> Result<()> {
|
||||
|
|
@ -901,6 +1173,125 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_dev_with_value() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.1.0.dev4"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("dev=42"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 0.1.0.dev4 => 0.1.0.dev42
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.1.0.dev42"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_patch_and_dev_value() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.0.1"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("patch")
|
||||
.arg("--bump").arg("dev=66463664"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 0.0.1 => 0.0.2.dev66463664
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.0.2.dev66463664"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_patch_and_dev_explicit_values_sorted() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.1.2.dev3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("dev=0")
|
||||
.arg("--bump").arg("patch=10"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
myproject 0.1.2.dev3 => 0.1.10.dev0
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Audited in [TIME]
|
||||
");
|
||||
|
||||
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||
assert_snapshot!(
|
||||
pyproject,
|
||||
@r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "0.1.10.dev0"
|
||||
requires-python = ">=3.12"
|
||||
"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Bump major but the input version is .post
|
||||
#[test]
|
||||
fn version_major_post() -> Result<()> {
|
||||
|
|
@ -941,6 +1332,84 @@ requires-python = ">=3.12"
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_stable_with_value_fails() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("stable=1"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: `--bump stable` does not accept a value
|
||||
");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_empty_value_fails() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("patch="), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: `--bump` values cannot be empty
|
||||
");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bump_invalid_numeric_value_fails() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "myproject"
|
||||
version = "1.2.3"
|
||||
requires-python = ">=3.12"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.version()
|
||||
.arg("--bump").arg("dev=foo"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: invalid numeric value `foo` for `--bump dev`
|
||||
");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// --bump stable but it decreases the version
|
||||
#[test]
|
||||
fn bump_decrease_stable() -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,14 @@ The `--bump` option supports the following common version components: `major`, `
|
|||
`stable`, `alpha`, `beta`, `rc`, `post`, and `dev`. When provided more than once, the components
|
||||
will be applied in order, from largest (`major`) to smallest (`dev`).
|
||||
|
||||
You can optionally provide a numeric value with `--bump <component>=<value>` to set the resulting
|
||||
component explicitly:
|
||||
|
||||
```console
|
||||
$ uv version --bump patch --bump dev=66463664
|
||||
hello-world 0.0.1 => 0.0.2.dev66463664
|
||||
```
|
||||
|
||||
To move from a stable to pre-release version, bump one of the major, minor, or patch components in
|
||||
addition to the pre-release component:
|
||||
|
||||
|
|
|
|||
|
|
@ -1168,7 +1168,7 @@ uv version [OPTIONS] [VALUE]
|
|||
<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>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[=value]</i></dt><dd><p>Update the project version using the given semantics</p>
|
||||
<p>This flag can be passed multiple times.</p>
|
||||
<p>Possible values:</p>
|
||||
<ul>
|
||||
|
|
|
|||
Loading…
Reference in New Issue