From cdb8497cebb72a81160c41ac6aa49f34e005033a Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Wed, 11 Sep 2024 11:25:03 +0800 Subject: [PATCH 1/3] feat(cli): add `--token` option to `self update` command Signed-off-by: Frost Ming --- crates/uv-cli/src/lib.rs | 4 ++++ crates/uv/src/commands/self_update.rs | 10 +++++++++- crates/uv/src/lib.rs | 8 ++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index daf02811e819..ed7833430cd6 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -427,6 +427,10 @@ pub enum SelfCommand { pub struct SelfUpdateArgs { /// Update to the specified version. If not provided, uv will update to the latest version. pub target_version: Option, + + /// Specify a github token for authentication during the update process. + #[arg(long, env = "UV_GITHUB_TOKEN")] + pub token: Option, } #[derive(Args)] diff --git a/crates/uv/src/commands/self_update.rs b/crates/uv/src/commands/self_update.rs index edf6f4c43b3a..9fb23f6bf9ba 100644 --- a/crates/uv/src/commands/self_update.rs +++ b/crates/uv/src/commands/self_update.rs @@ -11,10 +11,18 @@ use crate::commands::ExitStatus; use crate::printer::Printer; /// Attempt to update the uv binary. -pub(crate) async fn self_update(version: Option, printer: Printer) -> Result { +pub(crate) async fn self_update( + version: Option, + token: Option, + printer: Printer, +) -> Result { let mut updater = AxoUpdater::new_for("uv"); updater.disable_installer_output(); + if let Some(token) = token { + updater.set_github_token(&token); + } + // Load the "install receipt" for the current binary. If the receipt is not found, then // uv was likely installed via a package manager. let Ok(updater) = updater.load_receipt() else { diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 9360320a3acc..0ee3a7c2720f 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -766,8 +766,12 @@ async fn run(cli: Cli) -> Result { } #[cfg(feature = "self-update")] Commands::Self_(SelfNamespace { - command: SelfCommand::Update(SelfUpdateArgs { target_version }), - }) => commands::self_update(target_version, printer).await, + command: + SelfCommand::Update(SelfUpdateArgs { + target_version, + token, + }), + }) => commands::self_update(target_version, token, printer).await, Commands::Version { output_format } => { commands::version(output_format, &mut stdout())?; Ok(ExitStatus::Success) From 0f7cfa1ecf5c7ac2d7cf3a2928320959dabb3277 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Thu, 12 Sep 2024 09:05:57 +0800 Subject: [PATCH 2/3] fix: adopt review suggestions Signed-off-by: Frost Ming --- crates/uv-cli/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index ed7833430cd6..7f589049d0f2 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -428,7 +428,8 @@ pub struct SelfUpdateArgs { /// Update to the specified version. If not provided, uv will update to the latest version. pub target_version: Option, - /// Specify a github token for authentication during the update process. + /// A GitHub token for authentication. + /// A token is not required but can be used to reduce the chance of encountering rate limits. #[arg(long, env = "UV_GITHUB_TOKEN")] pub token: Option, } From 19096d2664e879d9689bd650300ed8890e00b277 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Thu, 12 Sep 2024 11:27:46 +0800 Subject: [PATCH 3/3] fix: show a friendly message when GitHub API rate limit is exceeded Signed-off-by: Frost Ming --- Cargo.lock | 1 + crates/uv/Cargo.toml | 1 + crates/uv/src/commands/self_update.rs | 26 ++++++++++++++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e121040f645d..08bd1fada869 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4464,6 +4464,7 @@ dependencies = [ "flate2", "fs-err", "futures", + "http", "ignore", "indexmap", "indicatif", diff --git a/crates/uv/Cargo.toml b/crates/uv/Cargo.toml index 2b65aed76dbd..dcce749f4aa3 100644 --- a/crates/uv/Cargo.toml +++ b/crates/uv/Cargo.toml @@ -55,6 +55,7 @@ ctrlc = { workspace = true } flate2 = { workspace = true, default-features = false } fs-err = { workspace = true, features = ["tokio"] } futures = { workspace = true } +http = { workspace = true } indexmap = { workspace = true } indicatif = { workspace = true } indoc = { workspace = true } diff --git a/crates/uv/src/commands/self_update.rs b/crates/uv/src/commands/self_update.rs index 9fb23f6bf9ba..f6372d72ce06 100644 --- a/crates/uv/src/commands/self_update.rs +++ b/crates/uv/src/commands/self_update.rs @@ -19,8 +19,8 @@ pub(crate) async fn self_update( let mut updater = AxoUpdater::new_for("uv"); updater.disable_installer_output(); - if let Some(token) = token { - updater.set_github_token(&token); + if let Some(ref token) = token { + updater.set_github_token(token); } // Load the "install receipt" for the current binary. If the receipt is not found, then @@ -129,11 +129,25 @@ pub(crate) async fn self_update( )?; } Err(err) => { - return Err(if let AxoupdateError::Reqwest(err) = err { - WrappedReqwestError::from(err).into() + return if let AxoupdateError::Reqwest(err) = err { + if err.status() == Some(http::StatusCode::FORBIDDEN) && token.is_none() { + writeln!( + printer.stderr(), + "{}", + format_args!( + "{}{} GitHub API rate limit exceeded. Please provide a GitHub token via the {} option.", + "error".red().bold(), + ":".bold(), + "`--token`".green().bold() + ) + )?; + Ok(ExitStatus::Error) + } else { + Err(WrappedReqwestError::from(err).into()) + } } else { - err.into() - }); + Err(err.into()) + }; } }