Download crates/forge_main/src/update.rs from SaylorTwift/forgecode: direct link, hf CLI and curl.
- Browser
- Download file 4 kB
-
https://huggingface.co/SaylorTwift/forgecode/resolve/main/crates/forge_main/src/update.rs
- Command line
-
hf download hf://SaylorTwift/forgecode/crates/forge_main/src/update.rs
-
curl -L -o update.rs https://huggingface.co/SaylorTwift/forgecode/resolve/main/crates/forge_main/src/update.rs
4 kB
| use std::sync::Arc; | |
| use colored::Colorize; | |
| use forge_api::API; | |
| use forge_config::{Update, UpdateFrequency}; | |
| use forge_select::ForgeWidget; | |
| use forge_tracker::VERSION; | |
| use update_informer::{Check, Version, registry}; | |
| /// Runs the official installation script to update Forge, failing silently. | |
| /// When `auto_update` is true, exits immediately after a successful update | |
| /// without prompting the user. | |
| async fn execute_update_command(api: Arc<impl API>, auto_update: bool) { | |
| // Spawn a new task that won't block the main application | |
| let output = api | |
| .execute_shell_command_raw("curl -fsSL https://forgecode.dev/cli | sh") | |
| .await; | |
| match output { | |
| Err(err) => { | |
| // Send an event to the tracker on failure | |
| // We don't need to handle this result since we're failing silently | |
| let _ = send_update_failure_event(&format!("Auto update failed {err}")).await; | |
| } | |
| Ok(output) => { | |
| if output.success() { | |
| let should_exit = if auto_update { | |
| true | |
| } else { | |
| let answer = forge_select::ForgeWidget::confirm( | |
| "You need to close forge to complete update. Do you want to close it now?", | |
| ) | |
| .with_default(true) | |
| .prompt(); | |
| answer.unwrap_or_default().unwrap_or_default() | |
| }; | |
| if should_exit { | |
| std::process::exit(0); | |
| } | |
| } else { | |
| let exit_output = match output.code() { | |
| Some(code) => format!("Process exited with code: {code}"), | |
| None => "Process exited without code".to_string(), | |
| }; | |
| let _ = | |
| send_update_failure_event(&format!("Auto update failed, {exit_output}",)).await; | |
| } | |
| } | |
| } | |
| } | |
| async fn confirm_update(version: Version) -> bool { | |
| let answer = ForgeWidget::confirm(format!( | |
| "Confirm upgrade from {} -> {} (latest)?", | |
| VERSION.to_string().bold().white(), | |
| version.to_string().bold().white() | |
| )) | |
| .with_default(true) | |
| .prompt(); | |
| match answer { | |
| Ok(Some(result)) => result, | |
| Ok(None) => false, // User canceled | |
| Err(_) => false, // Error occurred | |
| } | |
| } | |
| fn should_check_for_updates(frequency: &UpdateFrequency) -> bool { | |
| !matches!(frequency, UpdateFrequency::Never) | |
| } | |
| /// Checks if there is an update available | |
| pub async fn on_update(api: Arc<impl API>, update: Option<&Update>) { | |
| let update = update.cloned().unwrap_or_default(); | |
| let frequency = update.frequency.unwrap_or_default(); | |
| if !should_check_for_updates(&frequency) { | |
| return; | |
| } | |
| let auto_update = update.auto_update.unwrap_or_default(); | |
| // Check if version is development version, in which case we skip the update | |
| // check | |
| if VERSION.contains("dev") || VERSION == "0.1.0" { | |
| // Skip update for development version 0.1.0 | |
| return; | |
| } | |
| let informer = update_informer::new(registry::GitHub, "tailcallhq/forgecode", VERSION) | |
| .interval(frequency.into()); | |
| if let Some(version) = informer.check_version().ok().flatten() | |
| && (auto_update || confirm_update(version).await) | |
| { | |
| execute_update_command(api, auto_update).await; | |
| } | |
| } | |
| /// Sends an event to the tracker when an update fails | |
| async fn send_update_failure_event(error_msg: &str) -> anyhow::Result<()> { | |
| tracing::error!(error = error_msg, "Update failed"); | |
| // Always return Ok since we want to fail silently | |
| Ok(()) | |
| } | |
| mod tests { | |
| use pretty_assertions::assert_eq; | |
| use super::*; | |
| fn test_should_skip_update_check_when_frequency_is_never() { | |
| let fixture = UpdateFrequency::Never; | |
| let actual = should_check_for_updates(&fixture); | |
| let expected = false; | |
| assert_eq!(actual, expected); | |
| } | |
| } | |