[Add] Auto updates
This commit is contained in:
parent
c6fa1a01da
commit
8df387bea5
5 changed files with 209 additions and 5 deletions
70
Cargo.lock
generated
70
Cargo.lock
generated
|
|
@ -381,6 +381,12 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aster"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "258989846dd255a1e0eeef92d425d345477c9999433cecc9f0879f4549d5e5c9"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.89"
|
||||
|
|
@ -1028,9 +1034,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a043dc74da1e37d6afe657061213aa6f425f855399a11d3463c6ecccc4dfda1f"
|
||||
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
|
|
@ -1863,6 +1869,7 @@ name = "iota-util"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"hex",
|
||||
"hkdf",
|
||||
|
|
@ -1872,8 +1879,12 @@ dependencies = [
|
|||
"rand_core 0.6.4",
|
||||
"ratatui",
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_macros",
|
||||
"sha2",
|
||||
"sysinfo",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"ttp-core",
|
||||
"ttp-native",
|
||||
|
|
@ -2810,6 +2821,30 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quasi"
|
||||
version = "0.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94a532453b931a4483a5b2e40f0fe04aee35b6bc2c0eeec876f1bd2358a134d3"
|
||||
|
||||
[[package]]
|
||||
name = "quasi_codegen"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfb4a9a5410fdbdacbeda8063ddb8add9838dfd4cf50ac486db98abb762d8bd6"
|
||||
dependencies = [
|
||||
"aster",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quasi_macros"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adc2b36285ea5e54e4e267f83896267ff8c5aba4f66b2e7d186ed6d968f3715f"
|
||||
dependencies = [
|
||||
"quasi_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.9"
|
||||
|
|
@ -3375,6 +3410,24 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_codegen"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da68810d845f8e33a80243c28794650397056cbe7aea4c9c7516f55d1061c94e"
|
||||
dependencies = [
|
||||
"aster",
|
||||
"quasi",
|
||||
"quasi_macros",
|
||||
"serde_codegen_internals",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_codegen_internals"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b0115c5c602e81c61b787fb0f0fa76a614f8dbe9100b2b59b7d590155672c80"
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
|
|
@ -3408,6 +3461,15 @@ dependencies = [
|
|||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_macros"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3cf1c01933271e1e72bb788e0499d1bca8af2c09efcc3ddc0b04ff22d080b83"
|
||||
dependencies = [
|
||||
"serde_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
|
|
@ -4010,7 +4072,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|||
[[package]]
|
||||
name = "ttp-core"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.methanium.net/Tensamin/TTP.git#bacbcb0e38791cf1a38cf5851beb20d5645002ba"
|
||||
source = "git+https://git.methanium.net/Tensamin/TTP.git#2322bdced8183e970405d5017cd87ba805309a4c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
|
|
@ -4022,7 +4084,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ttp-native"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.methanium.net/Tensamin/TTP.git#bacbcb0e38791cf1a38cf5851beb20d5645002ba"
|
||||
source = "git+https://git.methanium.net/Tensamin/TTP.git#2322bdced8183e970405d5017cd87ba805309a4c"
|
||||
dependencies = [
|
||||
"quinn",
|
||||
"rustls",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
mod consent_state;
|
||||
use iota_util::update_util::check_update;
|
||||
use pnet::datalink::NetworkInterface;
|
||||
use tokio::time::{Duration, sleep};
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ async fn main() {
|
|||
println!("You can find this at 'agreements'!");
|
||||
return;
|
||||
}
|
||||
check_update();
|
||||
iota_state::setup();
|
||||
|
||||
let main_screen = MainScreen::new(ui.clone()).await;
|
||||
|
|
|
|||
|
|
@ -25,3 +25,8 @@ x448 = { version = "*" }
|
|||
hkdf = "0.12.4"
|
||||
once_cell = "1.21.3"
|
||||
hex = "*"
|
||||
serde = "1.0.228"
|
||||
tempfile = "3.27.0"
|
||||
anyhow = "1.0.102"
|
||||
semver = "1.0.28"
|
||||
serde_macros = "0.8.9"
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ pub mod crypto_helper;
|
|||
pub mod crypto_util;
|
||||
pub mod file_util;
|
||||
pub mod langu;
|
||||
pub mod update_util;
|
||||
|
|
|
|||
134
iota-util/src/update_util.rs
Normal file
134
iota-util/src/update_util.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/* This file is used for the auto update function for the Iota.
|
||||
* It connects to the git server from methanium and checks if
|
||||
* the version has updated inside the cargo.toml file.
|
||||
* It is made by Yolokit and pasted in by AlexEmmet */
|
||||
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
use std::fs::File;
|
||||
use std::io::copy;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
const API_BASE: &str = "https://git.methanium.net/api/v1";
|
||||
const OWNER: &str = "Tensamin";
|
||||
const REPO: &str = "Iota";
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
assets: Vec<Asset>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Asset {
|
||||
name: String,
|
||||
browser_download_url: String,
|
||||
}
|
||||
|
||||
async fn latest_release() -> Result<Release> {
|
||||
let url = format!("{API_BASE}/repos/{OWNER}/{REPO}/releases/latest");
|
||||
|
||||
let response = reqwest::get(&url)
|
||||
.await
|
||||
.context("failed to query latest release.")?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(anyhow!("release API returned {}", response.status()));
|
||||
}
|
||||
|
||||
Ok(response
|
||||
.json()
|
||||
.await
|
||||
.context("failed to parse release JSON")?)
|
||||
}
|
||||
|
||||
async fn parse_tag_version(tag: &str) -> Result<Version> {
|
||||
let normalized = tag.strip_prefix('v').unwrap_or(tag);
|
||||
Ok(Version::parse(normalized)?)
|
||||
}
|
||||
|
||||
async fn current_version() -> Result<Version> {
|
||||
Ok(Version::parse(CURRENT_VERSION)?)
|
||||
}
|
||||
|
||||
async fn asset_name_for_current_platform() -> String {
|
||||
let os = std::env::consts::OS;
|
||||
let arch = std::env::consts::ARCH;
|
||||
|
||||
match (os, arch) {
|
||||
("linux", "x86_64") => "iota-linux-x86_64".to_string(),
|
||||
("linux", "aarch64") => "iota-linux-aarch64".to_string(),
|
||||
("windows", "x86_64") => "iota-windows-x86_64.exe".to_string(),
|
||||
("macos", "x86_64") => "iota-macos-x86_64".to_string(),
|
||||
("macos", "aarch64") => "iota-macos-aarch64".to_string(),
|
||||
_ => panic!("unsupported platform: {os}/{arch}"),
|
||||
}
|
||||
}
|
||||
|
||||
async fn download_asset(url: &str) -> Result<NamedTempFile> {
|
||||
let mut response = reqwest::get(url)
|
||||
.await
|
||||
.context("failed to download asset")?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(anyhow!("asset download returned {}", response.status()));
|
||||
}
|
||||
|
||||
let tmp = NamedTempFile::new().context("failed to create temp file")?;
|
||||
let mut out = File::create(tmp.path()).context("failed to open temp file")?;
|
||||
|
||||
let bytes = response
|
||||
.bytes()
|
||||
.await
|
||||
.context("failed to read response bytes")?;
|
||||
|
||||
std::fs::write(tmp.path(), &bytes).context("failed to write file")?;
|
||||
|
||||
Ok(tmp)
|
||||
}
|
||||
|
||||
async fn check_for_update() -> Result<Option<Release>> {
|
||||
let current = current_version().await?;
|
||||
let release = latest_release().await?;
|
||||
let latest = parse_tag_version(&release.tag_name).await?;
|
||||
|
||||
if latest > current {
|
||||
Ok(Some(release))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
async fn perform_update() -> Result<bool> {
|
||||
let Some(release) = check_for_update().await? else {
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
let wanted_asset = asset_name_for_current_platform().await;
|
||||
|
||||
let asset = release
|
||||
.assets
|
||||
.iter()
|
||||
.find(|a| a.name == wanted_asset)
|
||||
.ok_or_else(|| anyhow!("no matching asset found: {}", wanted_asset))?;
|
||||
|
||||
log!("Downloading update: {}", asset.name);
|
||||
|
||||
let downloaded = download_asset(&asset.browser_download_url).await?;
|
||||
|
||||
self_replace::self_replace(downloaded.path())
|
||||
.context("failed to replace current executable")?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub async fn check_update() -> Result<bool> {
|
||||
if perform_update().await? {
|
||||
return Ok(true);
|
||||
} else {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue