Skip to main content

kasl/commands/
update.rs

1//! Application self-update command.
2//!
3//! Handles checking for and installing newer versions of kasl from GitHub releases with automatic binary replacement and backup capabilities.
4//!
5//! ## Features
6//!
7//! - **GitHub Integration**: Checks latest releases via GitHub API
8//! - **Cross-Platform Support**: Works on Windows, macOS, and Linux
9//! - **Safe Updates**: Creates backups before replacing binaries
10//! - **Watcher Management**: Automatically stops and restarts monitoring daemon
11//! - **Version Detection**: Compares current version with latest available
12//!
13//! ## Usage
14//!
15//! ```bash
16//! # Check for and install updates
17//! kasl update
18//! ```
19
20use crate::{
21    libs::{daemon, messages::Message, update::Updater},
22    msg_info, msg_success,
23};
24use anyhow::Result;
25
26/// Executes the application update process.
27///
28/// Performs a complete update workflow including version check, platform detection,
29/// download, extraction, and safe replacement of the current executable.
30///
31/// # Returns
32///
33/// Returns `Ok(())` on successful update or if no update is needed.
34/// Returns an error if the update process fails.
35pub async fn cmd() -> Result<()> {
36    // Check if watcher is currently running before update
37    let watcher_was_running = daemon::is_running();
38
39    if watcher_was_running {
40        msg_info!(Message::WatcherStoppingForUpdate);
41        daemon::stop()?;
42    }
43
44    // Create a new Updater instance with GitHub API configuration
45    let mut updater = Updater::new()?;
46
47    // Check GitHub API for the latest release version
48    let needs_update = updater.check_for_latest_release().await?;
49
50    if !needs_update {
51        msg_info!(Message::NoUpdateRequired);
52
53        // If watcher was running before update check, restart it
54        if watcher_was_running {
55            msg_info!(Message::WatcherRestartingAfterUpdate);
56            daemon::spawn()?;
57        }
58
59        return Ok(());
60    }
61
62    // Download and install the latest version
63    // This includes downloading the archive, extracting the binary,
64    // backing up the current executable, and replacing it
65    updater.perform_update().await?;
66
67    // Restart watcher if it was running before the update
68    if watcher_was_running {
69        msg_info!(Message::WatcherRestartingAfterUpdate);
70        daemon::spawn()?;
71    }
72
73    // Confirm successful update with version information
74    msg_success!(Message::UpdateCompleted {
75        app_name: updater.name,
76        version: updater.latest_version.as_deref().unwrap_or("unknown").to_string()
77    });
78
79    Ok(())
80}