Skip to main content

rusty_commit/commands/
update.rs

1use crate::cli::UpdateCommand;
2use crate::update::{check_for_update, perform_update, InstallMethod};
3use anyhow::Result;
4use colored::*;
5use semver::Version;
6
7pub async fn execute(cmd: UpdateCommand) -> Result<()> {
8    // If a specific version is requested
9    if let Some(target_version) = cmd.version {
10        return update_to_specific_version(&target_version, cmd.force).await;
11    }
12
13    // Check for updates
14    let update_info = check_for_update().await?;
15
16    println!("{}", "Checking for updates...".blue());
17    println!(
18        "Current version: {}",
19        format!("v{}", update_info.current_version).cyan()
20    );
21    println!(
22        "Latest version:  {}",
23        format!("v{}", update_info.latest_version).cyan()
24    );
25    println!(
26        "Install method:  {}",
27        format!("{:?}", update_info.install_method).cyan()
28    );
29
30    // If only checking
31    if cmd.check {
32        if update_info.needs_update {
33            println!(
34                "\n{}",
35                format!(
36                    "Update available! Run 'rco update' to update to v{}",
37                    update_info.latest_version
38                )
39                .yellow()
40            );
41        } else {
42            println!("\n{}", "You're running the latest version! 🎉".green());
43        }
44        return Ok(());
45    }
46
47    // Check if update is needed
48    if !update_info.needs_update && !cmd.force {
49        println!(
50            "\n{}",
51            "You're already running the latest version! 🎉".green()
52        );
53        println!(
54            "{}",
55            "Use --force to reinstall the current version.".dimmed()
56        );
57        return Ok(());
58    }
59
60    // Warn about unknown installation method
61    if update_info.install_method == InstallMethod::Unknown {
62        eprintln!(
63            "\n{}",
64            "Warning: Could not detect installation method.".yellow()
65        );
66        eprintln!(
67            "{}",
68            "Please update manually or use the install script:".yellow()
69        );
70        eprintln!(
71            "  {}",
72            "curl -fsSL https://raw.githubusercontent.com/hongkongkiwi/rusty-commit/main/install.sh | bash".cyan()
73        );
74        return Ok(());
75    }
76
77    // Confirm update
78    if !confirm_update(
79        &update_info.current_version,
80        &update_info.latest_version,
81        cmd.force,
82    )? {
83        println!("{}", "Update cancelled.".yellow());
84        return Ok(());
85    }
86
87    // Perform update
88    println!();
89    perform_update(&update_info).await?;
90
91    Ok(())
92}
93
94async fn update_to_specific_version(version_str: &str, force: bool) -> Result<()> {
95    // Clean version string (remove 'v' prefix if present)
96    let version_str = version_str.trim_start_matches('v');
97
98    // Validate version
99    let target_version = Version::parse(version_str)?;
100    let current_version = Version::parse(env!("CARGO_PKG_VERSION"))?;
101
102    // Check if already on this version
103    if target_version == current_version && !force {
104        println!(
105            "{}",
106            format!("Already running version v{}!", version_str).green()
107        );
108        println!(
109            "{}",
110            "Use --force to reinstall the current version.".dimmed()
111        );
112        return Ok(());
113    }
114
115    // Get installation method
116    let install_method = crate::update::detect_install_method()?;
117
118    if install_method == InstallMethod::Unknown {
119        eprintln!(
120            "{}",
121            "Warning: Could not detect installation method.".yellow()
122        );
123        eprintln!(
124            "{}",
125            "Please update manually or use the install script:".yellow()
126        );
127        eprintln!(
128            "  {}",
129            format!("curl -fsSL https://raw.githubusercontent.com/hongkongkiwi/rusty-commit/main/install.sh | bash -s -- --version v{}", version_str).cyan()
130        );
131        return Ok(());
132    }
133
134    // Create update info for specific version
135    let update_info = crate::update::UpdateInfo {
136        current_version: env!("CARGO_PKG_VERSION").to_string(),
137        latest_version: version_str.to_string(),
138        install_method,
139        executable_path: std::env::current_exe()?,
140        needs_update: true, // Force update
141    };
142
143    // Confirm update
144    if !confirm_update(
145        &update_info.current_version,
146        &update_info.latest_version,
147        force,
148    )? {
149        println!("{}", "Update cancelled.".yellow());
150        return Ok(());
151    }
152
153    // Perform update
154    println!();
155    perform_update(&update_info).await?;
156
157    Ok(())
158}
159
160fn confirm_update(current: &str, target: &str, force: bool) -> Result<bool> {
161    use std::io::{self, Write};
162
163    if force {
164        println!(
165            "\n{}",
166            format!("Force updating from v{} to v{}", current, target).yellow()
167        );
168        return Ok(true);
169    }
170
171    print!(
172        "\n{} ",
173        format!("Update from v{} to v{}? [Y/n]", current, target).yellow()
174    );
175    io::stdout().flush()?;
176
177    let mut input = String::new();
178    io::stdin().read_line(&mut input)?;
179
180    let input = input.trim().to_lowercase();
181    Ok(input.is_empty() || input == "y" || input == "yes")
182}