Skip to content

Commit fa4fc7c

Browse files
committed
🧹 installer: move logic into own module
1 parent 1d99e07 commit fa4fc7c

File tree

2 files changed

+169
-156
lines changed

2 files changed

+169
-156
lines changed

‎src/installer.rs‎

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
use crate::{check_regular_file, fl, utils, G_HELLO_WINDOW};
2+
3+
use std::fs;
4+
use std::io::{BufRead, BufReader};
5+
use std::path::Path;
6+
7+
use gtk::prelude::{BuilderExtManual, WidgetExt};
8+
9+
use serde::Deserialize;
10+
use subprocess::{Exec, Redirection};
11+
use tracing::{error, info};
12+
13+
#[derive(Deserialize)]
14+
struct Versions {
15+
#[serde(rename = "desktopISOVersion")]
16+
desktop_iso_version: String,
17+
#[serde(rename = "handheldISOVersion")]
18+
handheld_iso_version: String,
19+
}
20+
21+
fn outdated_version_check(message: String) -> bool {
22+
let edition_tag: String =
23+
fs::read_to_string("/etc/edition-tag").unwrap_or("desktop".into()).trim().into();
24+
let version_tag: String =
25+
fs::read_to_string("/etc/version-tag").unwrap_or("testing".into()).trim().into();
26+
27+
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
28+
29+
if version_tag.contains("testing") {
30+
utils::show_simple_dialog(
31+
window_ref,
32+
gtk::MessageType::Warning,
33+
&fl!("testing-iso-warning"),
34+
message.clone(),
35+
);
36+
return true;
37+
}
38+
39+
let response = reqwest::blocking::get("https://cachyos.org/versions.json");
40+
41+
if response.is_err() {
42+
utils::show_simple_dialog(
43+
window_ref,
44+
gtk::MessageType::Warning,
45+
&fl!("offline-error"),
46+
message.clone(),
47+
);
48+
return false;
49+
}
50+
51+
let versions = response.unwrap().json::<Versions>().unwrap();
52+
53+
let latest_version = if edition_tag.contains("desktop") {
54+
versions.desktop_iso_version
55+
} else {
56+
versions.handheld_iso_version
57+
}
58+
.trim()
59+
.to_owned();
60+
61+
if version_tag != latest_version {
62+
utils::show_simple_dialog(
63+
window_ref,
64+
gtk::MessageType::Warning,
65+
&fl!("outdated-version-warning"),
66+
message.clone(),
67+
);
68+
}
69+
true
70+
}
71+
72+
fn edition_compat_check(message: String) -> bool {
73+
let edition_tag = fs::read_to_string("/etc/edition-tag").unwrap_or("desktop".to_string());
74+
75+
if edition_tag == "handheld" {
76+
let profiles_path =
77+
format!("{}/handhelds/profiles.toml", chwd::consts::CHWD_PCI_CONFIG_DIR);
78+
79+
let handheld_profiles =
80+
chwd::profile::parse_profiles(&profiles_path).expect("Failed to parse profiles");
81+
let handheld_profile_names: Vec<_> =
82+
handheld_profiles.iter().map(|profile| &profile.name).collect();
83+
84+
let available_profiles = chwd::profile::get_available_profiles(false);
85+
86+
if available_profiles.iter().any(|profile| handheld_profile_names.contains(&&profile.name))
87+
{
88+
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
89+
utils::show_simple_dialog(
90+
window_ref,
91+
gtk::MessageType::Warning,
92+
&fl!("unsupported-hw-warning"),
93+
message.clone(),
94+
);
95+
return true;
96+
}
97+
}
98+
true
99+
}
100+
101+
fn connectivity_check(message: String) -> bool {
102+
let status = match reqwest::blocking::get("https://cachyos.org") {
103+
Ok(resp) => resp.status().is_success() || resp.status().is_server_error(),
104+
_ => false,
105+
};
106+
107+
if !status {
108+
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
109+
utils::show_simple_dialog(
110+
window_ref,
111+
gtk::MessageType::Error,
112+
&fl!("offline-error"),
113+
message,
114+
);
115+
return false;
116+
}
117+
true
118+
}
119+
120+
pub fn launch_installer(message: String) {
121+
// Spawn child process in separate thread.
122+
std::thread::spawn(move || {
123+
let builder = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().builder };
124+
125+
let install_btn: gtk::Button = builder.object("install").unwrap();
126+
install_btn.set_sensitive(false);
127+
128+
let checks = [connectivity_check, edition_compat_check, outdated_version_check];
129+
if !checks.iter().all(|x| x(message.clone())) {
130+
// if any check failed, return
131+
info!("Some ISO check failed!");
132+
install_btn.set_sensitive(true);
133+
return;
134+
}
135+
136+
// Spawning child process
137+
info!("ISO checks passed! Starting Installer..");
138+
let mut child = Exec::cmd("/usr/local/bin/calamares-online.sh")
139+
.stdout(Redirection::Pipe)
140+
.stderr(Redirection::Merge)
141+
.popen()
142+
.expect("Failed to spawn installer");
143+
144+
let child_out = child.stdout.take().unwrap();
145+
let child_read = BufReader::new(child_out);
146+
147+
// Read the output line by line until EOF
148+
for line_result in child_read.lines() {
149+
match line_result {
150+
Ok(line) => info!("{line}"),
151+
Err(e) => error!("Error reading output: {e}"),
152+
}
153+
}
154+
155+
let status = child.wait().expect("Failed to waiting for child");
156+
info!("Installer finished with status: {:?}", status);
157+
158+
install_btn.set_sensitive(true);
159+
});
160+
}
161+
162+
pub fn is_iso(preferences: &serde_json::Value) -> bool {
163+
Path::new(&preferences["live_path"].as_str().unwrap()).exists()
164+
&& check_regular_file(preferences["installer_path"].as_str().unwrap())
165+
}

‎src/main.rs‎

Lines changed: 4 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod config;
77
mod data_types;
88
mod embed_data;
99
mod gresource;
10+
mod installer;
1011
mod localization;
1112
mod logger;
1213
mod pages;
@@ -17,7 +18,6 @@ use data_types::*;
1718
use utils::*;
1819

1920
use std::collections::HashMap;
20-
use std::io::{BufRead, BufReader};
2121
use std::path::Path;
2222
use std::sync::{Arc, Mutex};
2323
use std::{fs, str};
@@ -31,8 +31,7 @@ use gtk::{gdk, glib, Builder, HeaderBar, Window};
3131
use i18n_embed::DesktopLanguageRequester;
3232
use once_cell::sync::Lazy;
3333
use serde_json::json;
34-
use subprocess::{Exec, Redirection};
35-
use tracing::{debug, error, info};
34+
use tracing::{debug, error};
3635
use unic_langid::LanguageIdentifier;
3736

3837
const RESPREFIX: &str = "/org/cachyos/hello";
@@ -43,155 +42,6 @@ static G_SAVE_JSON: Lazy<Mutex<serde_json::Value>> = Lazy::new(|| {
4342
});
4443
static mut G_HELLO_WINDOW: Option<Arc<HelloWindow>> = None;
4544

46-
#[derive(serde::Deserialize)]
47-
struct Versions {
48-
#[serde(rename = "desktopISOVersion")]
49-
desktop_iso_version: String,
50-
#[serde(rename = "handheldISOVersion")]
51-
handheld_iso_version: String,
52-
}
53-
54-
fn outdated_version_check(message: String) -> bool {
55-
let edition_tag: String =
56-
fs::read_to_string("/etc/edition-tag").unwrap_or("desktop".into()).trim().into();
57-
let version_tag: String =
58-
fs::read_to_string("/etc/version-tag").unwrap_or("testing".into()).trim().into();
59-
60-
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
61-
62-
if version_tag.contains("testing") {
63-
utils::show_simple_dialog(
64-
window_ref,
65-
gtk::MessageType::Warning,
66-
&fl!("testing-iso-warning"),
67-
message.clone(),
68-
);
69-
return true;
70-
}
71-
72-
let response = reqwest::blocking::get("https://cachyos.org/versions.json");
73-
74-
if response.is_err() {
75-
utils::show_simple_dialog(
76-
window_ref,
77-
gtk::MessageType::Warning,
78-
&fl!("offline-error"),
79-
message.clone(),
80-
);
81-
return false;
82-
}
83-
84-
let versions = response.unwrap().json::<Versions>().unwrap();
85-
86-
let latest_version = if edition_tag.contains("desktop") {
87-
versions.desktop_iso_version
88-
} else {
89-
versions.handheld_iso_version
90-
}
91-
.trim()
92-
.to_owned();
93-
94-
if version_tag != latest_version {
95-
utils::show_simple_dialog(
96-
window_ref,
97-
gtk::MessageType::Warning,
98-
&fl!("outdated-version-warning"),
99-
message.clone(),
100-
);
101-
}
102-
true
103-
}
104-
105-
fn edition_compat_check(message: String) -> bool {
106-
let edition_tag = fs::read_to_string("/etc/edition-tag").unwrap_or("desktop".to_string());
107-
108-
if edition_tag == "handheld" {
109-
let profiles_path =
110-
format!("{}/handhelds/profiles.toml", chwd::consts::CHWD_PCI_CONFIG_DIR);
111-
112-
let handheld_profiles =
113-
chwd::profile::parse_profiles(&profiles_path).expect("Failed to parse profiles");
114-
let handheld_profile_names: Vec<_> =
115-
handheld_profiles.iter().map(|profile| &profile.name).collect();
116-
117-
let available_profiles = chwd::profile::get_available_profiles(false);
118-
119-
if available_profiles.iter().any(|profile| handheld_profile_names.contains(&&profile.name))
120-
{
121-
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
122-
utils::show_simple_dialog(
123-
window_ref,
124-
gtk::MessageType::Warning,
125-
&fl!("unsupported-hw-warning"),
126-
message.clone(),
127-
);
128-
return true;
129-
}
130-
}
131-
true
132-
}
133-
134-
fn connectivity_check(message: String) -> bool {
135-
let status = match reqwest::blocking::get("https://cachyos.org") {
136-
Ok(resp) => resp.status().is_success() || resp.status().is_server_error(),
137-
_ => false,
138-
};
139-
140-
if !status {
141-
let window_ref = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().window };
142-
utils::show_simple_dialog(
143-
window_ref,
144-
gtk::MessageType::Error,
145-
&fl!("offline-error"),
146-
message,
147-
);
148-
return false;
149-
}
150-
true
151-
}
152-
153-
fn quick_message(message: String) {
154-
// Spawn child process in separate thread.
155-
std::thread::spawn(move || {
156-
let builder = unsafe { &G_HELLO_WINDOW.as_ref().unwrap().builder };
157-
158-
let install_btn: gtk::Button = builder.object("install").unwrap();
159-
install_btn.set_sensitive(false);
160-
161-
let checks = [connectivity_check, edition_compat_check, outdated_version_check];
162-
if !checks.iter().all(|x| x(message.clone())) {
163-
// if any check failed, return
164-
info!("Some ISO check failed!");
165-
install_btn.set_sensitive(true);
166-
return;
167-
}
168-
169-
// Spawning child process
170-
info!("ISO checks passed! Starting Installer..");
171-
let mut child = Exec::cmd("/usr/local/bin/calamares-online.sh")
172-
.stdout(Redirection::Pipe)
173-
.stderr(Redirection::Merge)
174-
.popen()
175-
.expect("Failed to spawn installer");
176-
177-
let child_out = child.stdout.take().unwrap();
178-
let child_read = BufReader::new(child_out);
179-
180-
// Read the output line by line until EOF
181-
for line_result in child_read.lines() {
182-
match line_result {
183-
Ok(line) => info!("{line}"),
184-
Err(e) => error!("Error reading output: {e}"),
185-
}
186-
}
187-
188-
let status = child.wait().expect("Failed to waiting for child");
189-
info!("Installer finished with status: {:?}", status);
190-
191-
install_btn.set_sensitive(true);
192-
});
193-
}
194-
19545
fn show_about_dialog() {
19646
let main_window: &Window = unsafe { G_HELLO_WINDOW.as_ref().unwrap().window.as_ref() };
19747
let logo_path = format!("/usr/share/icons/hicolor/scalable/apps/{APP_ID}.svg");
@@ -422,9 +272,7 @@ fn build_ui(application: &gtk::Application) {
422272
autostart_switch.set_active(autostart);
423273

424274
// Live systems
425-
if (Path::new(&preferences["live_path"].as_str().unwrap()).exists())
426-
&& (check_regular_file(preferences["installer_path"].as_str().unwrap()))
427-
{
275+
if installer::is_iso(&preferences) {
428276
let installlabel: gtk::Label = builder.object("installlabel").unwrap();
429277
installlabel.set_visible(true);
430278

@@ -610,7 +458,7 @@ fn on_action_clicked(param: &[glib::Value]) -> Option<glib::Value> {
610458
let widget = param[0].get::<gtk::Widget>().unwrap();
611459
match widget.widget_name().as_str() {
612460
"install" => {
613-
quick_message(fl!("calamares-install-type"));
461+
installer::launch_installer(fl!("calamares-install-type"));
614462
None
615463
},
616464
"autostart" => {

0 commit comments

Comments
 (0)