|
| 1 | +use crate::github::api::GithubApi; |
| 2 | +use crate::updater::constants::{GH_REPO, GH_USER}; |
| 3 | +use crate::updater::release; |
| 4 | +use crate::updater::release::{ReleaseVersion, ReleaseVersionCompareResult}; |
| 5 | +use crate::{ERROR, INFO, SUCCESS}; |
| 6 | +use console::Term; |
| 7 | +use futures::StreamExt; |
| 8 | +use log::debug; |
| 9 | +use std::env::temp_dir; |
| 10 | +use tokio::fs::{create_dir_all, File}; |
| 11 | +use tokio::io; |
| 12 | +use tokio::io::BufWriter; |
| 13 | + |
| 14 | +pub async fn self_update(term: &Term, github_api: &mut GithubApi) -> anyhow::Result<()> { |
| 15 | + let latest_version = github_api |
| 16 | + .get_latest_release_version(GH_USER, GH_REPO) |
| 17 | + .await?; |
| 18 | + |
| 19 | + let current_version = release::get_current_release_version(); |
| 20 | + |
| 21 | + let compared_version_result = |
| 22 | + release::compare_latest_release_to_current_version(&latest_version, ¤t_version); |
| 23 | + |
| 24 | + if compared_version_result == ReleaseVersionCompareResult::EqualOrNewer { |
| 25 | + term.write_line(&format!( |
| 26 | + "{} You are already on the latest version {}", |
| 27 | + SUCCESS, latest_version |
| 28 | + ))?; |
| 29 | + return Ok(()); |
| 30 | + } |
| 31 | + |
| 32 | + term.write_line(&format!( |
| 33 | + "{} New version {} available, updating...", |
| 34 | + INFO, latest_version |
| 35 | + ))?; |
| 36 | + |
| 37 | + let temp_folder_name = temp_dir().join("red_oxide-update"); |
| 38 | + |
| 39 | + create_dir_all(&temp_folder_name).await?; |
| 40 | + |
| 41 | + debug!("Created temp folder: {:?}", temp_folder_name); |
| 42 | + |
| 43 | + let filename = match release::get_filename_for_current_target_triple() { |
| 44 | + Ok(file_name) => file_name, |
| 45 | + Err(_) => { |
| 46 | + term.write_line(&format!( |
| 47 | + "{} No prebuild found for your platform, you'll have to build it yourself.", |
| 48 | + ERROR |
| 49 | + ))?; |
| 50 | + return Ok(()); |
| 51 | + } |
| 52 | + }; |
| 53 | + |
| 54 | + debug!("Got Github release filename: {}", filename); |
| 55 | + |
| 56 | + let mut file_byte_stream = github_api |
| 57 | + .get_latest_release_file_by_name(GH_USER, GH_REPO, filename.as_str()) |
| 58 | + .await?; |
| 59 | + |
| 60 | + let temp_file_path = temp_folder_name.join("red_oxide"); |
| 61 | + |
| 62 | + let file = File::create(&temp_file_path).await?; |
| 63 | + |
| 64 | + let mut buffered_file = BufWriter::new(file); |
| 65 | + |
| 66 | + while let Some(item) = file_byte_stream.next().await { |
| 67 | + io::copy(&mut item?.as_ref(), &mut buffered_file).await?; |
| 68 | + } |
| 69 | + |
| 70 | + debug!("Downloaded new release to: {:?}", temp_file_path); |
| 71 | + |
| 72 | + let current_exe = std::env::current_exe()?; |
| 73 | + |
| 74 | + let current_exe_renamed = current_exe.clone().parent().unwrap().join("red_oxide_old"); |
| 75 | + |
| 76 | + tokio::fs::rename(¤t_exe, ¤t_exe_renamed).await?; |
| 77 | + |
| 78 | + debug!("Renamed current executable to: {:?}", current_exe_renamed); |
| 79 | + |
| 80 | + tokio::fs::rename(&temp_file_path, ¤t_exe).await?; |
| 81 | + |
| 82 | + debug!("Renamed temporary downloaded file to {:?}", current_exe); |
| 83 | + |
| 84 | + tokio::fs::remove_dir(&temp_folder_name).await?; |
| 85 | + |
| 86 | + debug!("Removed temp folder: {:?}", &temp_folder_name); |
| 87 | + |
| 88 | + term.write_line(&format!( |
| 89 | + "{} Updated to version {} (be aware that the old executable will be deleted on next use)", |
| 90 | + SUCCESS, latest_version |
| 91 | + ))?; |
| 92 | + |
| 93 | + Ok(()) |
| 94 | +} |
0 commit comments