mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Merge b0879af032
into f609e1ddaf
This commit is contained in:
commit
41d7f125d3
11 changed files with 1338 additions and 50 deletions
|
@ -532,8 +532,11 @@ pub struct VersionArgs {
|
||||||
pub value: Option<String>,
|
pub value: Option<String>,
|
||||||
|
|
||||||
/// Update the project version using the given semantics
|
/// Update the project version using the given semantics
|
||||||
|
///
|
||||||
|
/// 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)]
|
#[arg(group = "operation", long)]
|
||||||
pub bump: Option<VersionBump>,
|
pub bump: Vec<VersionBump>,
|
||||||
|
|
||||||
/// Don't write a new version to the `pyproject.toml`
|
/// Don't write a new version to the `pyproject.toml`
|
||||||
///
|
///
|
||||||
|
@ -608,7 +611,9 @@ pub struct VersionArgs {
|
||||||
pub python: Option<Maybe<String>>,
|
pub python: Option<Maybe<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, clap::ValueEnum)]
|
// Note that the ordering of the variants is significant, as when given a list of operations
|
||||||
|
// to perform, we sort them and apply them in order, so users don't have to think too hard about it.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
|
||||||
pub enum VersionBump {
|
pub enum VersionBump {
|
||||||
/// Increase the major version (1.2.3 => 2.0.0)
|
/// Increase the major version (1.2.3 => 2.0.0)
|
||||||
Major,
|
Major,
|
||||||
|
@ -616,6 +621,37 @@ pub enum VersionBump {
|
||||||
Minor,
|
Minor,
|
||||||
/// Increase the patch version (1.2.3 => 1.2.4)
|
/// Increase the patch version (1.2.3 => 1.2.4)
|
||||||
Patch,
|
Patch,
|
||||||
|
/// Make the version stable (1.2.3b4.post5.dev6 => 1.2.3)
|
||||||
|
///
|
||||||
|
/// This intentionally clears `.postN` and preserves `+local`
|
||||||
|
Stable,
|
||||||
|
/// Increase the alpha version (1.2.3a4 => 1.2.3a5)
|
||||||
|
Alpha,
|
||||||
|
/// Increase the beta version (1.2.3b4 => 1.2.3b5)
|
||||||
|
Beta,
|
||||||
|
/// Increase the rc version (1.2.3rc4 => 1.2.3rc5)
|
||||||
|
Rc,
|
||||||
|
/// Increase the post version (1.2.3.post5 => 1.2.3.post6)
|
||||||
|
Post,
|
||||||
|
/// Increase the dev version (1.2.3a4.dev6 => 1.2.3.dev7)
|
||||||
|
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)]
|
#[derive(Args)]
|
||||||
|
|
|
@ -29,8 +29,8 @@ pub use version_ranges::{
|
||||||
};
|
};
|
||||||
pub use {
|
pub use {
|
||||||
version::{
|
version::{
|
||||||
LocalSegment, LocalVersion, LocalVersionSlice, MIN_VERSION, Operator, OperatorParseError,
|
BumpCommand, LocalSegment, LocalVersion, LocalVersionSlice, MIN_VERSION, Operator,
|
||||||
Prerelease, PrereleaseKind, Version, VersionParseError, VersionPattern,
|
OperatorParseError, Prerelease, PrereleaseKind, Version, VersionParseError, VersionPattern,
|
||||||
VersionPatternParseError,
|
VersionPatternParseError,
|
||||||
},
|
},
|
||||||
version_specifier::{
|
version_specifier::{
|
||||||
|
|
|
@ -643,6 +643,90 @@ impl Version {
|
||||||
self.with_release(release)
|
self.with_release(release)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Various "increment the version" operations
|
||||||
|
pub fn bump(&mut self, bump: BumpCommand) {
|
||||||
|
// This code operates on the understanding that the components of a version form
|
||||||
|
// the following hierarchy:
|
||||||
|
//
|
||||||
|
// major > minor > patch > stable > pre > post > dev
|
||||||
|
//
|
||||||
|
// Any updates to something earlier in the hierarchy should clear all values lower
|
||||||
|
// in the hierarchy. So for instance:
|
||||||
|
//
|
||||||
|
// if you bump `minor`, then clear: patch, pre, post, dev
|
||||||
|
// if you bump `pre`, then clear: post, dev
|
||||||
|
//
|
||||||
|
// ...and so on.
|
||||||
|
//
|
||||||
|
// If you bump a value that doesn't exist, it will be set to "1".
|
||||||
|
//
|
||||||
|
// The special "stable" mode has no value, bumping it clears: pre, post, dev.
|
||||||
|
let full = self.make_full();
|
||||||
|
|
||||||
|
match bump {
|
||||||
|
BumpCommand::BumpRelease { index } => {
|
||||||
|
// Clear all sub-release items
|
||||||
|
full.pre = None;
|
||||||
|
full.post = None;
|
||||||
|
full.dev = None;
|
||||||
|
|
||||||
|
// Use `max` here to try to do 0.2 => 0.3 instead of 0.2 => 0.3.0
|
||||||
|
let old_parts = &full.release;
|
||||||
|
let len = old_parts.len().max(index + 1);
|
||||||
|
let new_release_vec = (0..len)
|
||||||
|
.map(|i| match i.cmp(&index) {
|
||||||
|
// 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,
|
||||||
|
// Everything after the bumped value becomes 0
|
||||||
|
Ordering::Greater => 0,
|
||||||
|
})
|
||||||
|
.collect::<Vec<u64>>();
|
||||||
|
full.release = new_release_vec;
|
||||||
|
}
|
||||||
|
BumpCommand::MakeStable => {
|
||||||
|
// Clear all sub-release items
|
||||||
|
full.pre = None;
|
||||||
|
full.post = None;
|
||||||
|
full.dev = None;
|
||||||
|
}
|
||||||
|
BumpCommand::BumpPrerelease { kind } => {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
full.pre = Some(Prerelease { kind, number: 1 });
|
||||||
|
}
|
||||||
|
BumpCommand::BumpPost => {
|
||||||
|
// Clear sub-post items
|
||||||
|
full.dev = None;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
} else {
|
||||||
|
full.dev = Some(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the min-release component and return the updated version.
|
/// Set the min-release component and return the updated version.
|
||||||
///
|
///
|
||||||
/// The "min" component is internal-only, and does not exist in PEP 440.
|
/// The "min" component is internal-only, and does not exist in PEP 440.
|
||||||
|
@ -879,6 +963,27 @@ 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
|
||||||
|
BumpRelease {
|
||||||
|
/// The release component to bump (0 is major, 1 is minor, 2 is patch)
|
||||||
|
index: usize,
|
||||||
|
},
|
||||||
|
/// Bump the prerelease component
|
||||||
|
BumpPrerelease {
|
||||||
|
/// prerelease component to bump
|
||||||
|
kind: PrereleaseKind,
|
||||||
|
},
|
||||||
|
/// Bump to the associated stable release
|
||||||
|
MakeStable,
|
||||||
|
/// Bump the post component
|
||||||
|
BumpPost,
|
||||||
|
/// Bump the dev component
|
||||||
|
BumpDev,
|
||||||
|
}
|
||||||
|
|
||||||
/// A small representation of a version.
|
/// A small representation of a version.
|
||||||
///
|
///
|
||||||
/// This representation is used for a (very common) subset of versions: the
|
/// This representation is used for a (very common) subset of versions: the
|
||||||
|
@ -4043,4 +4148,351 @@ mod tests {
|
||||||
assert_eq!(size_of::<VersionSmall>(), size_of::<usize>() * 2);
|
assert_eq!(size_of::<VersionSmall>(), size_of::<usize>() * 2);
|
||||||
assert_eq!(size_of::<Version>(), size_of::<usize>() * 2);
|
assert_eq!(size_of::<Version>(), size_of::<usize>() * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test major bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_major() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!2.0.0.0+local");
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 0 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!3.0.0.0+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test minor bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_minor() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.8.0.0+local");
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 1 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.9.0.0+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test patch bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_patch() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
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 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.4.0+local");
|
||||||
|
version.bump(BumpCommand::BumpRelease { index: 2 });
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.5.0+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test alpha bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_alpha() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "0a1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.5a1");
|
||||||
|
|
||||||
|
// three digit
|
||||||
|
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5.3.6a1");
|
||||||
|
|
||||||
|
// four digit
|
||||||
|
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.2.3.4a1");
|
||||||
|
|
||||||
|
// All the version junk
|
||||||
|
let mut version = "5!1.7.3.5b2.post345.dev456+local"
|
||||||
|
.parse::<Version>()
|
||||||
|
.unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5a1+local");
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5a2+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test beta bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_beta() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "0b1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.5b1");
|
||||||
|
|
||||||
|
// three digit
|
||||||
|
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5.3.6b1");
|
||||||
|
|
||||||
|
// four digit
|
||||||
|
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.2.3.4b1");
|
||||||
|
|
||||||
|
// All the version junk
|
||||||
|
let mut version = "5!1.7.3.5a2.post345.dev456+local"
|
||||||
|
.parse::<Version>()
|
||||||
|
.unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b1+local");
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test rc bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_rc() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "0rc1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.5rc1");
|
||||||
|
|
||||||
|
// three digit
|
||||||
|
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5.3.6rc1");
|
||||||
|
|
||||||
|
// four digit
|
||||||
|
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.2.3.4rc1");
|
||||||
|
|
||||||
|
// All the version junk
|
||||||
|
let mut version = "5!1.7.3.5b2.post345.dev456+local"
|
||||||
|
.parse::<Version>()
|
||||||
|
.unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc1+local");
|
||||||
|
version.bump(BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
});
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5rc2+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test post bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_post() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPost);
|
||||||
|
assert_eq!(version.to_string().as_str(), "0.post1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpPost);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post1+local");
|
||||||
|
version.bump(BumpCommand::BumpPost);
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5b2.post2+local");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test dev bumping
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn bump_dev() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpDev);
|
||||||
|
assert_eq!(version.to_string().as_str(), "0.dev1");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::BumpDev);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
assert_eq!(
|
||||||
|
version.to_string().as_str(),
|
||||||
|
"5!1.7.3.5b2.post345.dev1+local"
|
||||||
|
);
|
||||||
|
version.bump(BumpCommand::BumpDev);
|
||||||
|
assert_eq!(
|
||||||
|
version.to_string().as_str(),
|
||||||
|
"5!1.7.3.5b2.post345.dev2+local"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test stable setting
|
||||||
|
/// Explicitly using the string display because we want to preserve formatting where possible!
|
||||||
|
#[test]
|
||||||
|
fn make_stable() {
|
||||||
|
// one digit
|
||||||
|
let mut version = "0".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "0");
|
||||||
|
|
||||||
|
// two digit
|
||||||
|
let mut version = "1.5".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.5");
|
||||||
|
|
||||||
|
// three digit
|
||||||
|
let mut version = "5.3.6".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "5.3.6");
|
||||||
|
|
||||||
|
// four digit
|
||||||
|
let mut version = "1.2.3.4".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "1.2.3.4");
|
||||||
|
|
||||||
|
// All the version junk
|
||||||
|
let mut version = "5!1.7.3.5b2.post345+local".parse::<Version>().unwrap();
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
|
||||||
|
version.bump(BumpCommand::MakeStable);
|
||||||
|
assert_eq!(version.to_string().as_str(), "5!1.7.3.5+local");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{cmp::Ordering, path::Path};
|
|
||||||
|
|
||||||
use anyhow::{Context, Result, anyhow};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
@ -15,7 +15,7 @@ use uv_configuration::{
|
||||||
};
|
};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_normalize::DefaultExtras;
|
use uv_normalize::DefaultExtras;
|
||||||
use uv_pep440::Version;
|
use uv_pep440::{BumpCommand, PrereleaseKind, Version};
|
||||||
use uv_pep508::PackageName;
|
use uv_pep508::PackageName;
|
||||||
use uv_python::{PythonDownloads, PythonPreference, PythonRequest};
|
use uv_python::{PythonDownloads, PythonPreference, PythonRequest};
|
||||||
use uv_settings::PythonInstallMirrors;
|
use uv_settings::PythonInstallMirrors;
|
||||||
|
@ -55,7 +55,7 @@ pub(crate) fn self_version(
|
||||||
#[allow(clippy::fn_params_excessive_bools)]
|
#[allow(clippy::fn_params_excessive_bools)]
|
||||||
pub(crate) async fn project_version(
|
pub(crate) async fn project_version(
|
||||||
value: Option<String>,
|
value: Option<String>,
|
||||||
bump: Option<VersionBump>,
|
mut bump: Vec<VersionBump>,
|
||||||
short: bool,
|
short: bool,
|
||||||
output_format: VersionFormat,
|
output_format: VersionFormat,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
|
@ -105,7 +105,7 @@ pub(crate) async fn project_version(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Short-circuit early for a frozen read
|
// Short-circuit early for a frozen read
|
||||||
let is_read_only = value.is_none() && bump.is_none();
|
let is_read_only = value.is_none() && bump.is_empty();
|
||||||
if frozen && is_read_only {
|
if frozen && is_read_only {
|
||||||
return Box::pin(print_frozen_version(
|
return Box::pin(print_frozen_version(
|
||||||
project,
|
project,
|
||||||
|
@ -158,7 +158,8 @@ pub(crate) async fn project_version(
|
||||||
match Version::from_str(&value) {
|
match Version::from_str(&value) {
|
||||||
Ok(version) => Some(version),
|
Ok(version) => Some(version),
|
||||||
Err(err) => match &*value {
|
Err(err) => match &*value {
|
||||||
"major" | "minor" | "patch" => {
|
"major" | "minor" | "patch" | "alpha" | "beta" | "rc" | "dev" | "post"
|
||||||
|
| "stable" => {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
"Invalid version `{value}`, did you mean to pass `--bump {value}`?"
|
"Invalid version `{value}`, did you mean to pass `--bump {value}`?"
|
||||||
));
|
));
|
||||||
|
@ -168,8 +169,120 @@ pub(crate) async fn project_version(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if let Some(bump) = bump {
|
} else if !bump.is_empty() {
|
||||||
Some(bumped_version(&old_version, bump, printer)?)
|
// 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 beta` (only one ordering is ever useful)
|
||||||
|
bump.sort();
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
kind: PrereleaseKind::Alpha,
|
||||||
|
},
|
||||||
|
VersionBump::Beta => BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Beta,
|
||||||
|
},
|
||||||
|
VersionBump::Rc => BumpCommand::BumpPrerelease {
|
||||||
|
kind: PrereleaseKind::Rc,
|
||||||
|
},
|
||||||
|
VersionBump::Post => BumpCommand::BumpPost,
|
||||||
|
VersionBump::Dev => BumpCommand::BumpDev,
|
||||||
|
VersionBump::Stable => BumpCommand::MakeStable,
|
||||||
|
};
|
||||||
|
new_version.bump(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
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} didn't increase the version"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(new_version)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -569,35 +682,3 @@ fn print_version(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bumped_version(from: &Version, bump: VersionBump, printer: Printer) -> Result<Version> {
|
|
||||||
// All prereleasey details "carry to 0" with every currently supported mode of `--bump`
|
|
||||||
// We could go out of our way to preserve epoch information but no one uses those...
|
|
||||||
if from.any_prerelease() || from.is_post() || from.is_local() || from.epoch() > 0 {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"warning: prerelease information will be cleared as part of the version bump"
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = match bump {
|
|
||||||
VersionBump::Major => 0,
|
|
||||||
VersionBump::Minor => 1,
|
|
||||||
VersionBump::Patch => 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use `max` here to try to do 0.2 => 0.3 instead of 0.2 => 0.3.0
|
|
||||||
let old_parts = from.release();
|
|
||||||
let len = old_parts.len().max(index + 1);
|
|
||||||
let new_release_vec = (0..len)
|
|
||||||
.map(|i| match i.cmp(&index) {
|
|
||||||
// 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,
|
|
||||||
// Everything after the bumped value becomes 0
|
|
||||||
Ordering::Greater => 0,
|
|
||||||
})
|
|
||||||
.collect::<Vec<u64>>();
|
|
||||||
Ok(Version::new(new_release_vec))
|
|
||||||
}
|
|
||||||
|
|
|
@ -2040,7 +2040,7 @@ async fn run_project(
|
||||||
let strict = project_was_explicit
|
let strict = project_was_explicit
|
||||||
|| globals.preview.is_enabled()
|
|| globals.preview.is_enabled()
|
||||||
|| args.dry_run
|
|| args.dry_run
|
||||||
|| args.bump.is_some()
|
|| !args.bump.is_empty()
|
||||||
|| args.value.is_some()
|
|| args.value.is_some()
|
||||||
|| args.package.is_some();
|
|| args.package.is_some();
|
||||||
Box::pin(commands::project_version(
|
Box::pin(commands::project_version(
|
||||||
|
|
|
@ -1561,7 +1561,7 @@ impl RemoveSettings {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct VersionSettings {
|
pub(crate) struct VersionSettings {
|
||||||
pub(crate) value: Option<String>,
|
pub(crate) value: Option<String>,
|
||||||
pub(crate) bump: Option<VersionBump>,
|
pub(crate) bump: Vec<VersionBump>,
|
||||||
pub(crate) short: bool,
|
pub(crate) short: bool,
|
||||||
pub(crate) output_format: VersionFormat,
|
pub(crate) output_format: VersionFormat,
|
||||||
pub(crate) dry_run: bool,
|
pub(crate) dry_run: bool,
|
||||||
|
|
|
@ -512,7 +512,6 @@ requires-python = ">=3.12"
|
||||||
myproject 1.10.31.dev10 => 2.0.0
|
myproject 1.10.31.dev10 => 2.0.0
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: prerelease information will be cleared as part of the version bump
|
|
||||||
Resolved 1 package in [TIME]
|
Resolved 1 package in [TIME]
|
||||||
Audited in [TIME]
|
Audited in [TIME]
|
||||||
");
|
");
|
||||||
|
@ -550,10 +549,9 @@ requires-python = ">=3.12"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
myproject 1!2a3.post4.dev5+deadbeef6 => 3
|
myproject 1!2a3.post4.dev5+deadbeef6 => 1!3+deadbeef6
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: prerelease information will be cleared as part of the version bump
|
|
||||||
Resolved 1 package in [TIME]
|
Resolved 1 package in [TIME]
|
||||||
Audited in [TIME]
|
Audited in [TIME]
|
||||||
");
|
");
|
||||||
|
@ -564,7 +562,295 @@ requires-python = ">=3.12"
|
||||||
@r#"
|
@r#"
|
||||||
[project]
|
[project]
|
||||||
name = "myproject"
|
name = "myproject"
|
||||||
version = "3"
|
version = "1!3+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass a ton of bump flags to a complex version
|
||||||
|
// The flags are in a messy order and some are duplicated,
|
||||||
|
// Under extremely permissive semantics this could be allowed, but right
|
||||||
|
// now it fails for a dozen reasons!
|
||||||
|
#[test]
|
||||||
|
fn many_bump_complex() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("major")
|
||||||
|
.arg("--bump").arg("patch")
|
||||||
|
.arg("--bump").arg("alpha")
|
||||||
|
.arg("--bump").arg("minor")
|
||||||
|
.arg("--bump").arg("dev")
|
||||||
|
.arg("--bump").arg("minor")
|
||||||
|
.arg("--bump").arg("post")
|
||||||
|
.arg("--bump").arg("post"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump post` cannot be combined with any other `--bump`
|
||||||
|
");
|
||||||
|
|
||||||
|
let pyproject = fs_err::read_to_string(&pyproject_toml)?;
|
||||||
|
assert_snapshot!(
|
||||||
|
pyproject,
|
||||||
|
@r#"
|
||||||
|
[project]
|
||||||
|
name = "myproject"
|
||||||
|
version = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump stable
|
||||||
|
#[test]
|
||||||
|
fn bump_stable() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("stable"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump alpha
|
||||||
|
#[test]
|
||||||
|
fn bump_alpha() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("alpha"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4a6+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4a6+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump beta
|
||||||
|
#[test]
|
||||||
|
fn bump_beta() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("beta"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4b1+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4b1+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump rc
|
||||||
|
#[test]
|
||||||
|
fn bump_rc() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("rc"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4rc1+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4rc1+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump post
|
||||||
|
#[test]
|
||||||
|
fn bump_post() -> 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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("post"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4a5.post7+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4a5.post7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump dev
|
||||||
|
#[test]
|
||||||
|
fn bump_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 = "9!2.3.4a5.post6.dev7+deadbeef6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("dev"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 9!2.3.4a5.post6.dev7+deadbeef6 => 9!2.3.4a5.post6.dev8+deadbeef6
|
||||||
|
|
||||||
|
----- 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 = "9!2.3.4a5.post6.dev8+deadbeef6"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
@ -594,7 +880,6 @@ requires-python = ">=3.12"
|
||||||
myproject 1.10.31.post10 => 2.0.0
|
myproject 1.10.31.post10 => 2.0.0
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: prerelease information will be cleared as part of the version bump
|
|
||||||
Resolved 1 package in [TIME]
|
Resolved 1 package in [TIME]
|
||||||
Audited in [TIME]
|
Audited in [TIME]
|
||||||
");
|
");
|
||||||
|
@ -612,6 +897,317 @@ requires-python = ">=3.12"
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --bump stable but it decreases the version
|
||||||
|
#[test]
|
||||||
|
fn bump_decrease_stable() -> 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.post6"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("stable"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: 2.3.4.post6 => 2.3.4 didn't increase the version
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump alpha but it decreases the version by reverting beta
|
||||||
|
#[test]
|
||||||
|
fn bump_decrease_alpha_beta() -> 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.4b5"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("alpha"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: 2.3.4b5 => 2.3.4a1 didn't increase the version
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump alpha but it decreases the version from a stable
|
||||||
|
#[test]
|
||||||
|
fn bump_decrease_alpha_stable() -> 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("alpha"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: 2.3.4 => 2.3.4a1 didn't increase the version; when moving to a prerelease you also need to increase the release `--bump patch`?
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump major twice
|
||||||
|
#[test]
|
||||||
|
fn bump_double_major() -> 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")
|
||||||
|
.arg("--bump").arg("major"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump` can only take one of `major`, `minor`, `patch`
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump alpha twice
|
||||||
|
#[test]
|
||||||
|
fn bump_double_alpha() -> 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("alpha")
|
||||||
|
.arg("--bump").arg("alpha"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump` can only take one of `alpha`, `beta`, `rc`, `dev`
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump stable --bump major
|
||||||
|
#[test]
|
||||||
|
fn bump_stable_major() -> 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("stable")
|
||||||
|
.arg("--bump").arg("major"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump stable` isn't needed if you're already passing `--bump major`
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump major --bump alpha
|
||||||
|
#[test]
|
||||||
|
fn bump_alpha_major() -> 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")
|
||||||
|
.arg("--bump").arg("alpha"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 2.3.4 => 3.0.0a1
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Audited in [TIME]
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump major --bump minor
|
||||||
|
#[test]
|
||||||
|
fn bump_minor_major() -> 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")
|
||||||
|
.arg("--bump").arg("alpha"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 2.3.4 => 3.0.0a1
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Audited in [TIME]
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump alpha --bump dev
|
||||||
|
#[test]
|
||||||
|
fn bump_alpha_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 = "2.3.4"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.version()
|
||||||
|
.arg("--bump").arg("alpha")
|
||||||
|
.arg("--bump").arg("dev"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump` can only take one of `alpha`, `beta`, `rc`, `dev`
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump major --bump dev
|
||||||
|
#[test]
|
||||||
|
fn bump_dev_major() -> 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")
|
||||||
|
.arg("--bump").arg("dev"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
myproject 2.3.4 => 3.0.0.dev1
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 1 package in [TIME]
|
||||||
|
Audited in [TIME]
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --bump major --bump post
|
||||||
|
#[test]
|
||||||
|
fn bump_post_major() -> 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")
|
||||||
|
.arg("--bump").arg("post"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: `--bump post` cannot be combined with any other `--bump`
|
||||||
|
");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Set version --dry-run
|
// Set version --dry-run
|
||||||
#[test]
|
#[test]
|
||||||
fn version_set_dry() -> Result<()> {
|
fn version_set_dry() -> Result<()> {
|
||||||
|
|
|
@ -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;
|
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`.
|
however, uv will still respect explicit attempts to build the project such as invoking `uv build`.
|
||||||
|
|
||||||
|
## Project versioning
|
||||||
|
|
||||||
## Project environment path
|
## Project environment path
|
||||||
|
|
||||||
The `UV_PROJECT_ENVIRONMENT` environment variable can be used to configure the project virtual
|
The `UV_PROJECT_ENVIRONMENT` environment variable can be used to configure the project virtual
|
||||||
|
|
|
@ -55,6 +55,83 @@ Alternatively, `uv build <SRC>` will build the package in the specified director
|
||||||
running `uv build --no-sources` to ensure that the package builds correctly when `tool.uv.sources`
|
running `uv build --no-sources` to ensure that the package builds correctly when `tool.uv.sources`
|
||||||
is disabled, as is the case when using other build tools, like [`pypa/build`](https://github.com/pypa/build).
|
is disabled, as is the case when using other build tools, like [`pypa/build`](https://github.com/pypa/build).
|
||||||
|
|
||||||
|
## Updating your version
|
||||||
|
|
||||||
|
The `uv version` command provides conveniences for updating the version of your package before you
|
||||||
|
publish it.
|
||||||
|
[See the project docs for reading your package's version](./projects.md#managing-version).
|
||||||
|
|
||||||
|
To set the the exact version of your package, just pass that version:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version 1.0.0
|
||||||
|
hello-world 0.7.0 => 1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to preview the change without actually applying it, use the `--dry-run` flag:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version 2.0.0 --dry-run
|
||||||
|
hello-world 1.0.0 => 2.0.0
|
||||||
|
$ uv version
|
||||||
|
hello-world 1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to change the version of a particular package, use the `--package` flag:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --package hello-world 1.2.3
|
||||||
|
hello-world 1.0.0 => 1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
To increase the version of your package, use the `--bump` flag:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --bump minor
|
||||||
|
hello-world 1.2.3 => 1.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
The `--bump` flag can be passed multiple times, and uv will run them in the following order that
|
||||||
|
prevents bumps from clobbering eachother:
|
||||||
|
|
||||||
|
```text
|
||||||
|
major > minor > patch > stable > alpha > beta > rc > post > dev
|
||||||
|
```
|
||||||
|
|
||||||
|
When you're on a stable version and want to start shipping prereleases, you'll want to bump the
|
||||||
|
release and the prerelease:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --bump patch --bump beta
|
||||||
|
hello-world 1.3.0 => 1.3.1b1
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
If you only bump the prerelease here it will actually decrease the current version.
|
||||||
|
`uv version` will error if that ever happens. If you intended to do that, you can pass
|
||||||
|
`--allow-decreases` to disable the check.
|
||||||
|
|
||||||
|
When you're on a prerelease and want to ship another, you can just bump the prerelease:
|
||||||
|
|
||||||
|
```console
|
||||||
|
uv version --bump beta
|
||||||
|
hello-world 1.3.0b1 => 1.3.1b2
|
||||||
|
```
|
||||||
|
|
||||||
|
When you're on a prerelease and want to ship a stable version, you can bump to stable:
|
||||||
|
|
||||||
|
```console
|
||||||
|
uv version --bump stable
|
||||||
|
hello-world 1.3.1b2 => 1.3.1
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
By default, when `uv version` modifies your package it will lock and sync your project to
|
||||||
|
ensure everything sees the change. To prevent locking and syncing, pass `--frozen`. To just
|
||||||
|
prevent syncing, pass `--no-sync`.
|
||||||
|
|
||||||
## Publishing your package
|
## Publishing your package
|
||||||
|
|
||||||
Publish your package with `uv publish`:
|
Publish your package with `uv publish`:
|
||||||
|
|
|
@ -160,6 +160,43 @@ version, while keeping the rest of the lockfile intact.
|
||||||
See the documentation on [managing dependencies](../concepts/projects/dependencies.md) for more
|
See the documentation on [managing dependencies](../concepts/projects/dependencies.md) for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
## Managing version
|
||||||
|
|
||||||
|
The `uv version` command can be used to read your package's version.
|
||||||
|
[See the publishing docs for updating your package's version](./package.md#updating-your-version).
|
||||||
|
|
||||||
|
To get the version of your package, run `uv version` with no other arguments:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version
|
||||||
|
hello-world 0.7.0
|
||||||
|
```
|
||||||
|
|
||||||
|
To get the version of a particular package, pass `--package`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --package myapp
|
||||||
|
myapp 1.2.3
|
||||||
|
```
|
||||||
|
|
||||||
|
To just get the version with no other output, pass `--short`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --short
|
||||||
|
0.7.0
|
||||||
|
```
|
||||||
|
|
||||||
|
To get the version as json, pass `--output-format json`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uv version --output-format json
|
||||||
|
{
|
||||||
|
"package_name": "hello-world",
|
||||||
|
"version": "0.7.0",
|
||||||
|
"commit_info": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Running commands
|
## Running commands
|
||||||
|
|
||||||
`uv run` can be used to run arbitrary scripts or commands in your project environment.
|
`uv run` can be used to run arbitrary scripts or commands in your project environment.
|
||||||
|
|
|
@ -785,11 +785,18 @@ uv version [OPTIONS] [VALUE]
|
||||||
<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>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>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</i></dt><dd><p>Update the project version using the given semantics</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>
|
<p>Possible values:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>major</code>: Increase the major version (1.2.3 => 2.0.0)</li>
|
<li><code>major</code>: Increase the major version (1.2.3 => 2.0.0)</li>
|
||||||
<li><code>minor</code>: Increase the minor version (1.2.3 => 1.3.0)</li>
|
<li><code>minor</code>: Increase the minor version (1.2.3 => 1.3.0)</li>
|
||||||
<li><code>patch</code>: Increase the patch version (1.2.3 => 1.2.4)</li>
|
<li><code>patch</code>: Increase the patch version (1.2.3 => 1.2.4)</li>
|
||||||
|
<li><code>stable</code>: Make the version stable (1.2.3b4.post5.dev6 => 1.2.3)</li>
|
||||||
|
<li><code>alpha</code>: Increase the alpha version (1.2.3a4 => 1.2.3a5)</li>
|
||||||
|
<li><code>beta</code>: Increase the beta version (1.2.3b4 => 1.2.3b5)</li>
|
||||||
|
<li><code>rc</code>: Increase the rc version (1.2.3rc4 => 1.2.3rc5)</li>
|
||||||
|
<li><code>post</code>: Increase the post version (1.2.3.post5 => 1.2.3.post6)</li>
|
||||||
|
<li><code>dev</code>: Increase the dev version (1.2.3a4.dev6 => 1.2.3.dev7)</li>
|
||||||
</ul></dd><dt id="uv-version--cache-dir"><a href="#uv-version--cache-dir"><code>--cache-dir</code></a> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
</ul></dd><dt id="uv-version--cache-dir"><a href="#uv-version--cache-dir"><code>--cache-dir</code></a> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||||
<p>Defaults to <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on macOS and Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
<p>Defaults to <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on macOS and Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||||
<p>To view the location of the cache directory, run <code>uv cache dir</code>.</p>
|
<p>To view the location of the cache directory, run <code>uv cache dir</code>.</p>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue