mirror of
https://github.com/yuzu-emu/liftinstall.git
synced 2024-11-25 09:35:47 +01:00
Add self-updating feature (closes #2)
This commit is contained in:
parent
b6fba61080
commit
351c4c7c1f
@ -60,6 +60,9 @@ impl BaseAttributes {
|
|||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub installing_message: String,
|
pub installing_message: String,
|
||||||
|
/// URL to a new updater, if required
|
||||||
|
#[serde(default)]
|
||||||
|
pub new_tool: Option<String>,
|
||||||
pub packages: Vec<PackageDescription>,
|
pub packages: Vec<PackageDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use reqwest::Client;
|
|||||||
/// Builds a customised HTTP client.
|
/// Builds a customised HTTP client.
|
||||||
pub fn build_client() -> Result<Client, String> {
|
pub fn build_client() -> Result<Client, String> {
|
||||||
Client::builder()
|
Client::builder()
|
||||||
.timeout(Duration::from_secs(5))
|
.timeout(Duration::from_secs(8))
|
||||||
.build()
|
.build()
|
||||||
.map_err(|x| format!("Unable to build cient: {:?}", x))
|
.map_err(|x| format!("Unable to build cient: {:?}", x))
|
||||||
}
|
}
|
||||||
|
130
src/installer.rs
130
src/installer.rs
@ -5,7 +5,9 @@
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
use std::env::var;
|
use std::env::var;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -13,6 +15,12 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
use std::io::copy;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
use config::BaseAttributes;
|
use config::BaseAttributes;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
|
|
||||||
@ -20,6 +28,7 @@ use sources::types::Version;
|
|||||||
|
|
||||||
use tasks::install::InstallTask;
|
use tasks::install::InstallTask;
|
||||||
use tasks::uninstall::UninstallTask;
|
use tasks::uninstall::UninstallTask;
|
||||||
|
use tasks::uninstall_global_shortcut::UninstallGlobalShortcutsTask;
|
||||||
use tasks::DependencyTree;
|
use tasks::DependencyTree;
|
||||||
|
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
@ -27,7 +36,10 @@ use logging::LoggingErrors;
|
|||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
|
|
||||||
use std::fs::remove_file;
|
use std::fs::remove_file;
|
||||||
use tasks::uninstall_global_shortcut::UninstallGlobalShortcutsTask;
|
|
||||||
|
use http;
|
||||||
|
|
||||||
|
use number_prefix::{decimal_prefix, Prefixed, Standalone};
|
||||||
|
|
||||||
/// A message thrown during the installation of packages.
|
/// A message thrown during the installation of packages.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -206,6 +218,122 @@ impl InstallerFramework {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verifies that the config has all requirements met (no need to update the
|
||||||
|
/// updater, for example). This will terminate if this is the case after applying
|
||||||
|
/// the correct actions.
|
||||||
|
pub fn update_updater(&mut self, messages: &Sender<InstallMessage>) -> Result<(), String> {
|
||||||
|
let tool = self
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.log_expect("Config should exist by now")
|
||||||
|
.new_tool
|
||||||
|
.as_ref()
|
||||||
|
.log_expect("Frontend asked for updater update when one doesn't exist");
|
||||||
|
|
||||||
|
let mut downloaded = 0;
|
||||||
|
let mut data_storage: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
|
http::stream_file(tool, |data, size| {
|
||||||
|
{
|
||||||
|
data_storage.extend_from_slice(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
downloaded += data.len();
|
||||||
|
|
||||||
|
let percentage = if size == 0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
(downloaded as f64) / (size as f64)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pretty print data volumes
|
||||||
|
let pretty_current = match decimal_prefix(downloaded as f64) {
|
||||||
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
|
};
|
||||||
|
let pretty_total = match decimal_prefix(size as f64) {
|
||||||
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(v) = messages.send(InstallMessage::Status(
|
||||||
|
format!(
|
||||||
|
"Downloading self-update ({} of {})...",
|
||||||
|
pretty_current, pretty_total
|
||||||
|
),
|
||||||
|
percentage as _,
|
||||||
|
)) {
|
||||||
|
error!("Failed to submit queue message: {:?}", v);
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
info!("Launching new updater...");
|
||||||
|
|
||||||
|
// Save to file in current dir
|
||||||
|
let current_exe = env::current_exe().log_expect("Current executable could not be found");
|
||||||
|
let path = current_exe
|
||||||
|
.parent()
|
||||||
|
.log_expect("Parent directory of executable could not be found");
|
||||||
|
|
||||||
|
let platform_extension = if cfg!(windows) {
|
||||||
|
"maintenancetool_new.exe"
|
||||||
|
} else {
|
||||||
|
"maintenancetool_new"
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_app = path.join(platform_extension);
|
||||||
|
|
||||||
|
let mut file_metadata = OpenOptions::new();
|
||||||
|
file_metadata.write(true).create(true);
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
|
file_metadata.mode(0o770);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut new_app_file = match file_metadata.open(&new_app) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(v) => return Err(format!("Unable to open installer binary: {:?}", v)),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(v) = copy(&mut Cursor::new(data_storage), &mut new_app_file) {
|
||||||
|
return Err(format!("Unable to copy installer binary: {:?}", v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current command line arguments
|
||||||
|
let args_file = path.join("args.json");
|
||||||
|
let args: Vec<String> = env::args_os()
|
||||||
|
.map(|x| {
|
||||||
|
x.to_str()
|
||||||
|
.log_expect("Unable to convert argument to String")
|
||||||
|
.to_string()
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
{
|
||||||
|
let new_app_file = match File::create(&args_file) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(v) => return Err(format!("Unable to open args file: {:?}", v)),
|
||||||
|
};
|
||||||
|
|
||||||
|
serde_json::to_writer(new_app_file, &args).log_expect("Unable to write args");
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_exe = env::current_exe().log_expect("Current executable could not be found");
|
||||||
|
|
||||||
|
// Launch this new process
|
||||||
|
Command::new(new_app)
|
||||||
|
.arg("--swap")
|
||||||
|
.arg(current_exe)
|
||||||
|
.spawn()
|
||||||
|
.log_expect("Unable to start child process");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
/// Saves the applications database.
|
/// Saves the applications database.
|
||||||
pub fn save_database(&self) -> Result<(), String> {
|
pub fn save_database(&self) -> Result<(), String> {
|
||||||
// We have to have a install path for us to be able to do anything
|
// We have to have a install path for us to be able to do anything
|
||||||
|
87
src/main.rs
87
src/main.rs
@ -61,12 +61,21 @@ use nfd::Response;
|
|||||||
|
|
||||||
use rest::WebServer;
|
use rest::WebServer;
|
||||||
|
|
||||||
|
use std::net::TcpListener;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
|
|
||||||
use std::net::TcpListener;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
|
use std::fs::remove_file;
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
@ -91,16 +100,26 @@ fn main() {
|
|||||||
|
|
||||||
let app_name = config.name.clone();
|
let app_name = config.name.clone();
|
||||||
|
|
||||||
let matches = App::new(format!("{} installer", app_name))
|
let app_about = format!("An interactive installer for {}", app_name);
|
||||||
|
let app = App::new(format!("{} installer", app_name))
|
||||||
.version(env!("CARGO_PKG_VERSION"))
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
.about(format!("An interactive installer for {}", app_name).as_ref())
|
.about(app_about.as_ref())
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("launcher")
|
Arg::with_name("launcher")
|
||||||
.long("launcher")
|
.long("launcher")
|
||||||
.value_name("TARGET")
|
.value_name("TARGET")
|
||||||
.help("Launches the specified executable after checking for updates")
|
.help("Launches the specified executable after checking for updates")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
).get_matches();
|
).arg(
|
||||||
|
Arg::with_name("swap")
|
||||||
|
.long("swap")
|
||||||
|
.value_name("TARGET")
|
||||||
|
.help("Internal usage - swaps around a new installer executable")
|
||||||
|
.takes_value(true),
|
||||||
|
);
|
||||||
|
|
||||||
|
let reinterpret_app = app.clone(); // In case a reparse is needed
|
||||||
|
let mut matches = app.get_matches();
|
||||||
|
|
||||||
info!("{} installer", app_name);
|
info!("{} installer", app_name);
|
||||||
|
|
||||||
@ -108,6 +127,66 @@ fn main() {
|
|||||||
let current_path = current_exe
|
let current_path = current_exe
|
||||||
.parent()
|
.parent()
|
||||||
.log_expect("Parent directory of executable could not be found");
|
.log_expect("Parent directory of executable could not be found");
|
||||||
|
|
||||||
|
// Check to see if we are currently in a self-update
|
||||||
|
if let Some(to_path) = matches.value_of("swap") {
|
||||||
|
let to_path = PathBuf::from(to_path);
|
||||||
|
|
||||||
|
// Sleep a little bit to allow Windows to close the previous file handle
|
||||||
|
thread::sleep(time::Duration::from_millis(3000));
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Swapping installer from {} to {}",
|
||||||
|
current_exe.display(),
|
||||||
|
to_path.display()
|
||||||
|
);
|
||||||
|
|
||||||
|
if cfg!(windows) {
|
||||||
|
use std::fs::copy;
|
||||||
|
|
||||||
|
copy(¤t_exe, &to_path).log_expect("Unable to copy new installer");
|
||||||
|
} else {
|
||||||
|
use std::fs::rename;
|
||||||
|
|
||||||
|
rename(¤t_exe, &to_path).log_expect("Unable to move new installer");
|
||||||
|
}
|
||||||
|
|
||||||
|
Command::new(to_path)
|
||||||
|
.spawn()
|
||||||
|
.log_expect("Unable to start child process");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let args_file = current_path.join("args.json");
|
||||||
|
|
||||||
|
if args_file.exists() {
|
||||||
|
let database: Vec<String> = {
|
||||||
|
let metadata_file =
|
||||||
|
File::open(&args_file).log_expect("Unable to open args file handle");
|
||||||
|
|
||||||
|
serde_json::from_reader(metadata_file).log_expect("Unable to read metadata file")
|
||||||
|
};
|
||||||
|
|
||||||
|
matches = reinterpret_app.get_matches_from(database);
|
||||||
|
|
||||||
|
info!("Reparsed command line arguments from original instance");
|
||||||
|
remove_file(args_file).log_expect("Unable to clean up args file");
|
||||||
|
|
||||||
|
if cfg!(windows) {
|
||||||
|
let updater_executable = current_path.join("maintenancetool.exe");
|
||||||
|
|
||||||
|
// Sleep a little bit to allow Windows to close the previous file handle
|
||||||
|
thread::sleep(time::Duration::from_millis(3000));
|
||||||
|
|
||||||
|
if updater_executable.exists() {
|
||||||
|
remove_file(updater_executable)
|
||||||
|
.log_expect("Unable to clean up previous updater file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load in metadata as to learn about the environment
|
||||||
let metadata_file = current_path.join("metadata.json");
|
let metadata_file = current_path.join("metadata.json");
|
||||||
let mut framework = if metadata_file.exists() {
|
let mut framework = if metadata_file.exists() {
|
||||||
info!("Using pre-existing metadata file: {:?}", metadata_file);
|
info!("Using pre-existing metadata file: {:?}", metadata_file);
|
||||||
|
@ -11,7 +11,6 @@ mod natives {
|
|||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/interop.rs"));
|
include!(concat!(env!("OUT_DIR"), "/interop.rs"));
|
||||||
@ -63,7 +62,12 @@ mod natives {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cleans up the installer
|
/// Cleans up the installer
|
||||||
pub fn burn_on_exit(path: &PathBuf) {
|
pub fn burn_on_exit() {
|
||||||
|
let current_exe = env::current_exe().log_expect("Current executable could not be found");
|
||||||
|
let path = current_exe
|
||||||
|
.parent()
|
||||||
|
.log_expect("Parent directory of executable could not be found");
|
||||||
|
|
||||||
// Need a cmd workaround here.
|
// Need a cmd workaround here.
|
||||||
let tool = path.join("maintenancetool.exe");
|
let tool = path.join("maintenancetool.exe");
|
||||||
let tool = tool
|
let tool = tool
|
||||||
@ -77,7 +81,7 @@ mod natives {
|
|||||||
.log_expect("Unable to convert log path to string")
|
.log_expect("Unable to convert log path to string")
|
||||||
.replace(" ", "\\ ");
|
.replace(" ", "\\ ");
|
||||||
|
|
||||||
let target_arguments = format!("ping 127.0.0.1 -n 6 > nul && del {} {}", tool, log);
|
let target_arguments = format!("ping 127.0.0.1 -n 3 > nul && del {} {}", tool, log);
|
||||||
|
|
||||||
info!("Launching cmd with {:?}", target_arguments);
|
info!("Launching cmd with {:?}", target_arguments);
|
||||||
|
|
||||||
@ -108,7 +112,13 @@ mod natives {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cleans up the installer
|
/// Cleans up the installer
|
||||||
pub fn burn_on_exit(path: &PathBuf) {
|
pub fn burn_on_exit() {
|
||||||
|
let current_exe =
|
||||||
|
std::env::current_exe().log_expect("Current executable could not be found");
|
||||||
|
let path = current_exe
|
||||||
|
.parent()
|
||||||
|
.log_expect("Parent directory of executable could not be found");
|
||||||
|
|
||||||
// Thank god for *nix platforms
|
// Thank god for *nix platforms
|
||||||
if let Err(e) = remove_file(path.join("/maintenancetool")) {
|
if let Err(e) = remove_file(path.join("/maintenancetool")) {
|
||||||
// No regular logging now.
|
// No regular logging now.
|
||||||
|
62
src/rest.rs
62
src/rest.rs
@ -207,12 +207,7 @@ impl Service for WebService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if framework.burn_after_exit {
|
if framework.burn_after_exit {
|
||||||
let path = framework
|
native::burn_on_exit();
|
||||||
.install_path
|
|
||||||
.as_ref()
|
|
||||||
.log_expect("No install path when one should have existed?");
|
|
||||||
|
|
||||||
native::burn_on_exit(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -289,6 +284,61 @@ impl Service for WebService {
|
|||||||
.with_body(rx)
|
.with_body(rx)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
// Updates the installer
|
||||||
|
(&Post, "/api/update-updater") => {
|
||||||
|
// We need to bit of pipelining to get this to work
|
||||||
|
let framework = self.framework.clone();
|
||||||
|
|
||||||
|
return Box::new(req.body().concat2().map(move |_b| {
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
let (tx, rx) = hyper::Body::pair();
|
||||||
|
|
||||||
|
// Startup a thread to do this operation for us
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut framework = framework
|
||||||
|
.write()
|
||||||
|
.log_expect("InstallerFramework has been dirtied");
|
||||||
|
|
||||||
|
if let Err(v) = framework.update_updater(&sender) {
|
||||||
|
error!("Self-update error occurred: {:?}", v);
|
||||||
|
if let Err(v) = sender.send(InstallMessage::Error(v)) {
|
||||||
|
error!("Failed to send self-update error: {:?}", v);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(v) = sender.send(InstallMessage::EOF) {
|
||||||
|
error!("Failed to send EOF to client: {:?}", v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn a thread for transforming messages to chunk messages
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut tx = tx;
|
||||||
|
loop {
|
||||||
|
let response = receiver
|
||||||
|
.recv()
|
||||||
|
.log_expect("Failed to receive message from runner thread");
|
||||||
|
|
||||||
|
if let InstallMessage::EOF = response {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut response = serde_json::to_string(&response)
|
||||||
|
.log_expect("Failed to render JSON logging response payload");
|
||||||
|
response.push('\n');
|
||||||
|
tx = tx
|
||||||
|
.send(Ok(response.into_bytes().into()))
|
||||||
|
.wait()
|
||||||
|
.log_expect("Failed to write JSON response payload to client");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Response::<hyper::Body>::new()
|
||||||
|
//.with_header(ContentLength(file.len() as u64))
|
||||||
|
.with_header(ContentType::plaintext())
|
||||||
|
.with_body(rx)
|
||||||
|
}));
|
||||||
|
}
|
||||||
// Streams the installation of a particular set of packages
|
// Streams the installation of a particular set of packages
|
||||||
(&Post, "/api/start-install") => {
|
(&Post, "/api/start-install") => {
|
||||||
// We need to bit of pipelining to get this to work
|
// We need to bit of pipelining to get this to work
|
||||||
|
@ -22,6 +22,13 @@ body, div, span, h1, h2, h3, h4, h5, h6 {
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
.tile.is-child > .box {
|
.tile.is-child > .box {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ function ajax(path, successCallback, failCallback, data) {
|
|||||||
failCallback = defaultFailHandler;
|
failCallback = defaultFailHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Making HTTP request to " + path);
|
||||||
|
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
|
|
||||||
req.addEventListener("load", function() {
|
req.addEventListener("load", function() {
|
||||||
@ -69,6 +71,8 @@ function ajax(path, successCallback, failCallback, data) {
|
|||||||
function stream_ajax(path, callback, successCallback, failCallback, data) {
|
function stream_ajax(path, callback, successCallback, failCallback, data) {
|
||||||
var req = new XMLHttpRequest();
|
var req = new XMLHttpRequest();
|
||||||
|
|
||||||
|
console.log("Making streaming HTTP request to " + path);
|
||||||
|
|
||||||
req.addEventListener("load", function() {
|
req.addEventListener("load", function() {
|
||||||
// The server can sometimes return a string error. Make sure we handle this.
|
// The server can sometimes return a string error. Make sure we handle this.
|
||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
|
@ -26,6 +26,17 @@ for (var i = 0; i < methods.length; i++) {
|
|||||||
intercept(methods[i]);
|
intercept(methods[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable F5
|
||||||
|
function disable_shortcuts(e) {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 116: // F5
|
||||||
|
e.preventDefault();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("keydown", disable_shortcuts);
|
||||||
|
|
||||||
document.getElementById("window-title").innerText = base_attributes.name + " Installer";
|
document.getElementById("window-title").innerText = base_attributes.name + " Installer";
|
||||||
|
|
||||||
function selectFileCallback(name) {
|
function selectFileCallback(name) {
|
||||||
|
@ -44,6 +44,12 @@ const DownloadConfig = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
choose_next_state: function() {
|
choose_next_state: function() {
|
||||||
|
// Update the updater if needed
|
||||||
|
if (app.config.new_tool) {
|
||||||
|
router.push("/install/updater");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (app.metadata.preexisting_install) {
|
if (app.metadata.preexisting_install) {
|
||||||
app.install_location = app.metadata.install_path;
|
app.install_location = app.metadata.install_path;
|
||||||
|
|
||||||
@ -153,6 +159,7 @@ const InstallPackages = {
|
|||||||
<div class="column has-padding">
|
<div class="column has-padding">
|
||||||
<h4 class="subtitle" v-if="$root.$data.metadata.is_launcher">Checking for updates...</h4>
|
<h4 class="subtitle" v-if="$root.$data.metadata.is_launcher">Checking for updates...</h4>
|
||||||
<h4 class="subtitle" v-else-if="is_uninstall">Uninstalling...</h4>
|
<h4 class="subtitle" v-else-if="is_uninstall">Uninstalling...</h4>
|
||||||
|
<h4 class="subtitle" v-else-if="is_updater_update">Downloading update for updater...</h4>
|
||||||
<h4 class="subtitle" v-else>Installing...</h4>
|
<h4 class="subtitle" v-else>Installing...</h4>
|
||||||
<div v-html="$root.$data.config.installing_message"></div>
|
<div v-html="$root.$data.config.installing_message"></div>
|
||||||
<br />
|
<br />
|
||||||
@ -168,11 +175,14 @@ const InstallPackages = {
|
|||||||
progress: 0.0,
|
progress: 0.0,
|
||||||
progress_message: "Please wait...",
|
progress_message: "Please wait...",
|
||||||
is_uninstall: false,
|
is_uninstall: false,
|
||||||
|
is_updater_update: false,
|
||||||
failed_with_error: false
|
failed_with_error: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function() {
|
created: function() {
|
||||||
this.is_uninstall = this.$route.params.kind === "uninstall";
|
this.is_uninstall = this.$route.params.kind === "uninstall";
|
||||||
|
this.is_updater_update = this.$route.params.kind === "updater";
|
||||||
|
console.log("Installer kind: " + this.$route.params.kind);
|
||||||
this.install();
|
this.install();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -190,8 +200,15 @@ const InstallPackages = {
|
|||||||
|
|
||||||
var that = this; // IE workaround
|
var that = this; // IE workaround
|
||||||
|
|
||||||
stream_ajax(this.is_uninstall ? "/api/uninstall" :
|
var targetUrl = "/api/start-install";
|
||||||
"/api/start-install", function(line) {
|
if (this.is_uninstall) {
|
||||||
|
targetUrl = "/api/uninstall";
|
||||||
|
}
|
||||||
|
if (this.is_updater_update) {
|
||||||
|
targetUrl = "/api/update-updater";
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_ajax(targetUrl, function(line) {
|
||||||
if (line.hasOwnProperty("Status")) {
|
if (line.hasOwnProperty("Status")) {
|
||||||
that.progress_message = line.Status[0];
|
that.progress_message = line.Status[0];
|
||||||
that.progress = line.Status[1] * 100;
|
that.progress = line.Status[1] * 100;
|
||||||
@ -206,10 +223,23 @@ const InstallPackages = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
if (app.metadata.is_launcher) {
|
if (that.is_updater_update) {
|
||||||
app.exit();
|
// Continue with what we were doing
|
||||||
} else if (!that.failed_with_error) {
|
if (app.metadata.is_launcher) {
|
||||||
router.push("/complete");
|
router.replace("/install/regular");
|
||||||
|
} else {
|
||||||
|
if (app.metadata.preexisting_install) {
|
||||||
|
router.replace("/modify");
|
||||||
|
} else {
|
||||||
|
router.replace("/packages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (app.metadata.is_launcher) {
|
||||||
|
app.exit();
|
||||||
|
} else if (!that.failed_with_error) {
|
||||||
|
router.replace("/complete");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, undefined, results);
|
}, undefined, results);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user