mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-11-17 09:47:36 +00:00
update/gupax: retry on failed bytes, add progress bar/spinner
This commit is contained in:
parent
6418a0ad2c
commit
8780b0684d
4 changed files with 58 additions and 30 deletions
|
@ -56,7 +56,7 @@ pub const HUGEPAGES_1GB: bool = true;
|
|||
// Gupax
|
||||
pub const GUPAX_UPDATE: &'static str = "Check for update on Gupax, P2Pool, and XMRig via GitHub's API and upgrade automatically";
|
||||
pub const GUPAX_AUTO_UPDATE: &'static str = "Automatically check for updates at startup";
|
||||
pub const GUPAX_UPDATE_VIA_TOR: &'static str = "Update through the Tor network. Gupax has Tor embedded, a Tor system proxy is not required.";
|
||||
pub const GUPAX_UPDATE_VIA_TOR: &'static str = "Update through the Tor network. Tor is embedded within Gupax; a Tor system proxy is not required";
|
||||
pub const GUPAX_AUTO_NODE: &'static str = "Automatically ping the community Monero nodes and select the fastest at startup for P2Pool";
|
||||
pub const GUPAX_ASK_BEFORE_QUIT: &'static str = "Ask before quitting if processes are still alive or if an update is in progress";
|
||||
pub const GUPAX_SAVE_BEFORE_QUIT: &'static str = "Automatically save any changed settings before quitting";
|
||||
|
|
24
src/gupax.rs
24
src/gupax.rs
|
@ -35,27 +35,41 @@ impl Gupax {
|
|||
// I have to pick one. This one seperates them though.
|
||||
let height = height/6.0;
|
||||
let width = width - SPACE;
|
||||
let updating = *update.updating.lock().unwrap();
|
||||
ui.vertical(|ui| {
|
||||
ui.set_enabled(!*update.updating.lock().unwrap());
|
||||
ui.set_enabled(!updating);
|
||||
if ui.add_sized([width, height], egui::Button::new("Check for updates")).on_hover_text(GUPAX_UPDATE).clicked() {
|
||||
update.path_p2pool = state.absolute_p2pool_path.display().to_string();
|
||||
update.path_xmrig = state.absolute_xmrig_path.display().to_string();
|
||||
update.tor = state.update_via_tor;
|
||||
let u = Arc::new(Mutex::new(update.clone()));
|
||||
let u = Arc::clone(&u);
|
||||
let u2 = Arc::new(Mutex::new(update.clone()));
|
||||
let u2 = Arc::clone(&u);
|
||||
thread::spawn(move|| {
|
||||
info!("Spawning update thread...");
|
||||
let handle = Update::start(u, version);
|
||||
info!("...........>");
|
||||
match Update::start(u, version) {
|
||||
Err(e) => {
|
||||
info!("Update | {} ... FAIL", e);
|
||||
*u2.lock().unwrap().msg.lock().unwrap() = MSG_FAILED.to_string();
|
||||
*u2.lock().unwrap().updating.lock().unwrap() = false;
|
||||
},
|
||||
_ => {
|
||||
info!("Update ... OK");
|
||||
*u2.lock().unwrap().msg.lock().unwrap() = MSG_SUCCESS.to_string();
|
||||
*u2.lock().unwrap().prog.lock().unwrap() = 100;
|
||||
*u2.lock().unwrap().updating.lock().unwrap() = false;
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
ui.vertical(|ui| {
|
||||
ui.set_enabled(*update.updating.lock().unwrap());
|
||||
ui.set_enabled(updating);
|
||||
let height = height/2.0;
|
||||
let msg = format!("{}{}{}{}", *update.msg.lock().unwrap(), " ... ", *update.prog.lock().unwrap(), "%");
|
||||
ui.add_sized([width, height], egui::Label::new(msg));
|
||||
// let range = *update.prog.lock().unwrap() as f32 / 100.0;
|
||||
if updating { ui.add_sized([width, height], egui::Spinner::new().size(height)); }
|
||||
ui.add_sized([width, height], egui::ProgressBar::new(*update.prog.lock().unwrap() as f32 / 100.0));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -582,6 +582,7 @@ impl eframe::App for App {
|
|||
ui.style_mut().override_text_style = Some(egui::TextStyle::Body);
|
||||
match self.tab {
|
||||
Tab::About => {
|
||||
info!("");
|
||||
ui.add_space(10.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
// Display [Gupax] banner at max, 1/4 the available length
|
||||
|
|
|
@ -163,7 +163,10 @@ const MSG_TMP: &'static str = "Creating temporary directory";
|
|||
const MSG_TOR: &'static str = "Creating Tor+HTTPS client";
|
||||
const MSG_HTTPS: &'static str = "Creating HTTPS client";
|
||||
const MSG_METADATA: &'static str = "Fetching package metadata";
|
||||
const MSG_ARCHIVE: &'static str = "Downloading packages";
|
||||
const MSG_COMPARE: &'static str = "Compare package versions";
|
||||
const MSG_DOWNLOAD: &'static str = "Downloading packages";
|
||||
pub const MSG_SUCCESS: &'static str = "Update successful";
|
||||
pub const MSG_FAILED: &'static str = "Update failed";
|
||||
|
||||
// These two are sequential and not async so no need for a constant message.
|
||||
// The package in question will be known at runtime, so that will be printed.
|
||||
|
@ -173,9 +176,10 @@ const MSG_ARCHIVE: &'static str = "Downloading packages";
|
|||
//---------------------------------------------------------------------------------------------------- Update struct/impl
|
||||
// Contains values needed during update
|
||||
// Progress bar structure:
|
||||
// 10% | Create tmp directory and pkg list
|
||||
// 15% | Create Tor/HTTPS client
|
||||
// 0% | Create tmp directory and pkg list
|
||||
// 10% | Create Tor/HTTPS client
|
||||
// 15% | Download Metadata (x3)
|
||||
// 15% | Compare Versions (x3)
|
||||
// 30% | Download Archive (x3)
|
||||
// 15% | Extract (x3)
|
||||
// 15% | Upgrade (x3)
|
||||
|
@ -273,7 +277,6 @@ impl Update {
|
|||
// so there will be some intermediate variables.
|
||||
info!("Update | Init | {} ... {}%", MSG_TMP.to_string(), *update.lock().unwrap().prog.lock().unwrap());
|
||||
let tmp_dir = Self::get_tmp_dir();
|
||||
*update.lock().unwrap().prog.lock().unwrap() += 10;
|
||||
|
||||
// Make Pkg vector
|
||||
let prog = update.lock().unwrap().prog.clone();
|
||||
|
@ -294,7 +297,8 @@ impl Update {
|
|||
let prog = *update.lock().unwrap().prog.lock().unwrap();
|
||||
info!("Update | Init | {} ... {}%", *update.lock().unwrap().msg.lock().unwrap(), prog);
|
||||
let client = Self::get_client(update.lock().unwrap().tor).await?;
|
||||
*update.lock().unwrap().prog.lock().unwrap() += 15;
|
||||
*update.lock().unwrap().prog.lock().unwrap() += 10;
|
||||
info!("Update | Init ... OK");
|
||||
|
||||
// Loop for metadata
|
||||
*update.lock().unwrap().msg.lock().unwrap() = MSG_METADATA.to_string();
|
||||
|
@ -322,6 +326,7 @@ impl Update {
|
|||
info!("Update | Metadata ... OK");
|
||||
|
||||
// Loop for version comparison
|
||||
*update.lock().unwrap().msg.lock().unwrap() = MSG_COMPARE.to_string();
|
||||
info!("Update | Compare | Starting version comparison...");
|
||||
let prog = update.lock().unwrap().prog.clone();
|
||||
let msg = update.lock().unwrap().msg.clone();
|
||||
|
@ -354,10 +359,13 @@ impl Update {
|
|||
}
|
||||
}
|
||||
}
|
||||
*update.lock().unwrap().prog.lock().unwrap() += 5;
|
||||
}
|
||||
info!("Update | Compare ... OK");
|
||||
|
||||
// Loop for download
|
||||
let mut handles: Vec<JoinHandle<()>> = vec![];
|
||||
*update.lock().unwrap().msg.lock().unwrap() = MSG_DOWNLOAD.to_string();
|
||||
info!("Update | Download | Starting download...");
|
||||
for pkg in vec2.iter() {
|
||||
// Clone data before async
|
||||
|
@ -380,11 +388,10 @@ impl Update {
|
|||
link = pkg.link_prefix.to_string() + &version + &pkg.link_suffix + &version + &pkg.link_extension;
|
||||
}
|
||||
info!("Update | Download | {} ... {}", pkg.name, link);
|
||||
let request = Pkg::get_request(link)?;
|
||||
let handle: JoinHandle<()> = tokio::spawn(async move {
|
||||
match client {
|
||||
ClientEnum::Tor(t) => Pkg::get_bytes(name, bytes, prog, t, request).await,
|
||||
ClientEnum::Https(h) => Pkg::get_bytes(name, bytes, prog, h, request).await,
|
||||
ClientEnum::Tor(t) => Pkg::get_bytes(name, bytes, prog, t, link).await,
|
||||
ClientEnum::Https(h) => Pkg::get_bytes(name, bytes, prog, h, link).await,
|
||||
};
|
||||
});
|
||||
handles.push(handle);
|
||||
|
@ -411,7 +418,6 @@ impl Update {
|
|||
}
|
||||
info!("Update | Extract ... OK");
|
||||
*update.lock().unwrap().updating.lock().unwrap() = false;
|
||||
std::process::exit(0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -491,8 +497,7 @@ impl Pkg {
|
|||
pub async fn get_metadata<C>(name: Name, new_ver: Arc<Mutex<String>>, prog: Arc<Mutex<u8>>, client: Client<C>, link: String) -> Result<(), Error>
|
||||
where C: hyper::client::connect::Connect + Clone + Send + Sync + 'static, {
|
||||
// Retry [3] times if version is not [v*]
|
||||
let mut n = 0;
|
||||
while n < 3 {
|
||||
for i in 0..3 {
|
||||
let request = Pkg::get_request(link.clone())?;
|
||||
let mut response = client.request(request).await?;
|
||||
let body = hyper::body::to_bytes(response.body_mut()).await?;
|
||||
|
@ -503,28 +508,36 @@ impl Pkg {
|
|||
info!("Update | Metadata | {} {} ... {}%", name, body.tag_name, *prog.lock().unwrap());
|
||||
return Ok(())
|
||||
}
|
||||
warn!("Update | Metadata | {} metadata fetch failed, retry [{}/3]...", name, n);
|
||||
n += 1;
|
||||
warn!("Update | Metadata | {} failed, retry [{}/3]...", name, i);
|
||||
}
|
||||
error!("Update | Metadata | {} metadata fetch failed", name);
|
||||
Err(anyhow!("Metadata fetch failed"))
|
||||
error!("Update | Metadata | {} failed", name);
|
||||
Err(anyhow!("{} | Metadata fetch failed", name))
|
||||
}
|
||||
|
||||
// Takes a [Request], fills the appropriate [Pkg]
|
||||
// [bytes] field with the [Archive/Standalone]
|
||||
pub async fn get_bytes<C>(name: Name, bytes: Arc<Mutex<bytes::Bytes>>, prog: Arc<Mutex<u8>>, client: Client<C>, request: Request<Body>) -> Result<(), anyhow::Error>
|
||||
pub async fn get_bytes<C>(name: Name, bytes: Arc<Mutex<bytes::Bytes>>, prog: Arc<Mutex<u8>>, client: Client<C>, link: String) -> Result<(), anyhow::Error>
|
||||
where C: hyper::client::connect::Connect + Clone + Send + Sync + 'static, {
|
||||
// GitHub sends a 302 redirect, so we must follow
|
||||
// the [Location] header... only if Reqwest had custom
|
||||
// connectors so I didn't have to manually do this...
|
||||
let response = client.request(request).await?;
|
||||
let request = Self::get_request(response.headers().get(hyper::header::LOCATION).unwrap().to_str()?.to_string())?;
|
||||
let response = client.request(request).await?;
|
||||
let body = hyper::body::to_bytes(response.into_body()).await?;
|
||||
*bytes.lock().unwrap() = body;
|
||||
*prog.lock().unwrap() += 10;
|
||||
info!("Update | Download | {} ... {}%", name, *prog.lock().unwrap());
|
||||
Ok(())
|
||||
// Also, retry [3] times if [Bytes] == empty
|
||||
for i in 0..3 {
|
||||
let request = Pkg::get_request(link.clone())?;
|
||||
let response = client.request(request).await?;
|
||||
let request = Self::get_request(response.headers().get(hyper::header::LOCATION).unwrap().to_str()?.to_string())?;
|
||||
let response = client.request(request).await?;
|
||||
let body = hyper::body::to_bytes(response.into_body()).await?;
|
||||
if ! body.is_empty() {
|
||||
*bytes.lock().unwrap() = body;
|
||||
*prog.lock().unwrap() += 10;
|
||||
info!("Update | Download | {} ... {}%", name, *prog.lock().unwrap());
|
||||
return Ok(())
|
||||
}
|
||||
warn!("Update | Metadata | {} download bytes are empty, retry [{}/3]...", name, i);
|
||||
}
|
||||
error!("Update | Download | {} failed", name);
|
||||
Err(anyhow!("{} | Download failed", name))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue