Add `--dry-run` support to `uv self update` (#9829)

See commentary at
https://github.com/astral-sh/uv/issues/9828#issuecomment-2537542100
regarding the limitations and future upstream changes needed.

```
❯ cargo build --features self-update
   Compiling uv v0.5.8 (/Users/zb/workspace/uv/crates/uv)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.28s
❯ cp ./target/debug/uv ~/.cargo/bin
❯ uv self update --dry-run
info: Checking for updates...
Nothing to do. You're on the latest version of uv (v0.5.8)
❯ uv self update --dry-run 0.5.7
info: Checking for updates...
Would update uv from v0.5.8 to v0.5.7
❯ vi ~/.config/uv/uv-receipt.json  # Edit the receipt to think its on an older version
❯ uv self update --dry-run
info: Checking for updates...
Would update uv from v0.5.8 to the latest version
```

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
Zanie Blue 2025-05-04 16:54:36 -05:00 committed by GitHub
parent 59e7287590
commit ea4284c041
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 41 additions and 2 deletions

View File

@ -589,6 +589,10 @@ pub struct SelfUpdateArgs {
/// A token is not required but can be used to reduce the chance of encountering rate limits.
#[arg(long, env = EnvVars::UV_GITHUB_TOKEN)]
pub token: Option<String>,
/// Run without performing the update.
#[arg(long)]
pub dry_run: bool,
}
#[derive(Args)]

View File

@ -15,6 +15,7 @@ use crate::printer::Printer;
pub(crate) async fn self_update(
version: Option<String>,
token: Option<String>,
dry_run: bool,
printer: Printer,
) -> Result<ExitStatus> {
let mut updater = AxoUpdater::new_for("uv");
@ -87,7 +88,38 @@ pub(crate) async fn self_update(
UpdateRequest::Latest
};
updater.configure_version_specifier(update_request);
updater.configure_version_specifier(update_request.clone());
if dry_run {
// TODO(charlie): `updater.fetch_release` isn't public, so we can't say what the latest
// version is.
if updater.is_update_needed().await? {
let version = match update_request {
UpdateRequest::Latest | UpdateRequest::LatestMaybePrerelease => {
"the latest version".to_string()
}
UpdateRequest::SpecificTag(version) | UpdateRequest::SpecificVersion(version) => {
format!("v{version}")
}
};
writeln!(
printer.stderr(),
"Would update uv from {} to {}",
format!("v{}", env!("CARGO_PKG_VERSION")).bold().white(),
version.bold().white(),
)?;
} else {
writeln!(
printer.stderr(),
"{}",
format_args!(
"You're on the latest version of uv ({})",
format!("v{}", env!("CARGO_PKG_VERSION")).bold().white()
)
)?;
}
return Ok(ExitStatus::Success);
}
// Run the updater. This involves a network request, since we need to determine the latest
// available version of uv.

View File

@ -1018,8 +1018,9 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
SelfCommand::Update(SelfUpdateArgs {
target_version,
token,
dry_run,
}),
}) => commands::self_update(target_version, token, printer).await,
}) => commands::self_update(target_version, token, dry_run, printer).await,
Commands::Self_(SelfNamespace {
command:
SelfCommand::Version {

View File

@ -9371,6 +9371,8 @@ uv self update [OPTIONS] [TARGET_VERSION]
<p>See <code>--project</code> to only change the project root directory.</p>
</dd><dt id="uv-self-update--dry-run"><a href="#uv-self-update--dry-run"><code>--dry-run</code></a></dt><dd><p>Run without performing the update</p>
</dd><dt id="uv-self-update--help"><a href="#uv-self-update--help"><code>--help</code></a>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>
</dd><dt id="uv-self-update--managed-python"><a href="#uv-self-update--managed-python"><code>--managed-python</code></a></dt><dd><p>Require use of uv-managed Python versions.</p>