liftinstall/src/main.rs

207 lines
5.9 KiB
Rust
Raw Normal View History

2018-08-03 11:52:31 +00:00
//! main.rs
//!
//! The main entrypoint for the application. Orchestrates the building of the installation
//! framework, and opens necessary HTTP servers/frontends.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
2018-08-04 07:15:27 +00:00
#![deny(unsafe_code)]
2018-08-04 08:35:00 +00:00
#![deny(missing_docs)]
2018-01-26 12:29:28 +00:00
extern crate wry;
2018-07-28 05:33:06 +00:00
extern crate futures;
extern crate hyper;
2018-08-03 11:52:31 +00:00
extern crate url;
2018-01-29 10:27:54 +00:00
2018-01-30 04:53:28 +00:00
extern crate number_prefix;
2018-01-30 04:54:44 +00:00
extern crate reqwest;
2018-01-30 04:53:28 +00:00
2018-01-27 03:27:41 +00:00
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;
2018-01-29 12:28:14 +00:00
extern crate regex;
extern crate semver;
2018-08-04 08:35:00 +00:00
extern crate dirs;
2018-08-08 02:47:32 +00:00
extern crate tar;
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
extern crate xz2;
2018-01-30 07:29:34 +00:00
extern crate zip;
2018-08-04 06:28:13 +00:00
extern crate fern;
#[macro_use]
extern crate log;
extern crate chrono;
2018-08-04 13:35:56 +00:00
extern crate clap;
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
#[cfg(windows)]
extern crate widestring;
#[cfg(windows)]
extern crate winapi;
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
#[cfg(not(windows))]
extern crate slug;
#[cfg(not(windows))]
extern crate sysinfo;
extern crate jsonwebtoken as jwt;
extern crate base64;
2018-08-08 02:47:32 +00:00
mod archives;
2018-01-27 03:27:41 +00:00
mod config;
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
mod frontend;
mod http;
2018-01-27 03:27:41 +00:00
mod installer;
mod logging;
2018-08-06 10:51:59 +00:00
mod native;
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
mod self_update;
mod sources;
mod tasks;
2018-01-26 12:29:28 +00:00
2018-01-27 03:27:41 +00:00
use installer::InstallerFramework;
2018-01-26 12:29:28 +00:00
use logging::LoggingErrors;
use std::path::PathBuf;
2018-08-04 13:35:56 +00:00
use clap::App;
use clap::Arg;
2018-08-07 05:34:57 +00:00
use config::BaseAttributes;
use std::fs;
use std::process::{exit, Command, Stdio};
2018-08-07 05:34:57 +00:00
2020-03-09 06:24:29 +00:00
const RAW_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/bootstrap.toml"));
2018-01-26 12:29:28 +00:00
fn main() {
let config = BaseAttributes::from_toml_str(RAW_CONFIG).expect("Config file could not be read");
2018-10-01 01:27:31 +00:00
logging::setup_logger(format!("{}_installer.log", config.name))
.expect("Unable to setup logging!");
2018-01-27 03:27:41 +00:00
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
// Parse CLI arguments
2018-08-07 05:34:57 +00:00
let app_name = config.name.clone();
2018-08-09 05:21:50 +00:00
let app_about = format!("An interactive installer for {}", app_name);
let app = App::new(format!("{} installer", app_name))
2018-08-04 13:35:56 +00:00
.version(env!("CARGO_PKG_VERSION"))
2018-08-09 05:21:50 +00:00
.about(app_about.as_ref())
2018-08-04 13:35:56 +00:00
.arg(
Arg::with_name("launcher")
.long("launcher")
.value_name("TARGET")
.help("Launches the specified executable after checking for updates")
.takes_value(true),
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
)
.arg(
2018-08-09 05:21:50 +00:00
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();
2018-08-04 13:35:56 +00:00
2018-08-04 06:28:13 +00:00
info!("{} installer", app_name);
2018-08-03 10:59:43 +00:00
// Handle self-updating if needed
let current_exe = std::env::current_exe().log_expect("Current executable could not be found");
let current_path = current_exe
.parent()
.log_expect("Parent directory of executable could not be found");
2018-08-09 05:21:50 +00:00
// Handle self-updating if needed
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
self_update::perform_swap(&current_exe, matches.value_of("swap"));
if let Some(new_matches) = self_update::check_args(reinterpret_app, current_path) {
matches = new_matches;
2018-08-09 05:21:50 +00:00
}
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
self_update::cleanup(current_path);
2018-08-09 05:21:50 +00:00
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
// Load in metadata + setup the installer framework
let mut fresh_install = false;
let metadata_file = current_path.join("metadata.json");
2018-08-04 13:35:56 +00:00
let mut framework = if metadata_file.exists() {
2018-08-04 06:28:13 +00:00
info!("Using pre-existing metadata file: {:?}", metadata_file);
InstallerFramework::new_with_db(config.clone(), current_path).unwrap_or_else(|e| {
error!("Failed to load metadata: {:?}", e);
warn!("Entering recovery mode");
InstallerFramework::new_recovery_mode(config, current_path)
})
2018-05-03 03:30:58 +00:00
} else {
2018-08-04 06:28:13 +00:00
info!("Starting fresh install");
fresh_install = true;
2018-05-03 03:30:58 +00:00
InstallerFramework::new(config)
};
2018-01-27 03:27:41 +00:00
// check for existing installs if we are running as a fresh install
let installed_path = PathBuf::from(framework.get_default_path().unwrap());
if fresh_install && installed_path.join("metadata.json").exists() {
info!("Existing install detected! Copying Trying to launch this install instead");
// Ignore the return value from this since it should exit the application if its successful
let _ = replace_existing_install(&current_exe, &installed_path);
}
2018-08-04 13:35:56 +00:00
let is_launcher = if let Some(string) = matches.value_of("launcher") {
framework.is_launcher = true;
framework.launcher_path = Some(string.to_string());
true
} else {
false
};
Update config files for v7 (#12) * platform: fix build on Linux and update web-view * deps: replace xz-decom with xz2 and update deps * platform: fix regression... ... that prevents the build on Windows * linux: implement platform-dependent functions * travis: add macos and windows CI * travis: use official Rust Docker image * Update Cargo.lock for new version * Break apart REST into separate services This cleans up locking, ensures consistent futures for all endpoints and enhances code re-use. * Clean up codebase, fixing minor errors * Update packages, use async client for downloading config While this has a hell of a lot more boilerplate, this is quite a bit cleaner. * Add explicit 'dyn's as per Rust nightly requirements * Migrate self updating functions to own module * Migrate assets to server module * Use patched web-view to fix dialogs, remove nfd * Implement basic dark mode * Revert window.close usage * ui: split files and use Webpack * frontend: ui: include prebuilt assets... ... and update rust side stuff * build: integrate webpack building into build.rs * Polish Vue UI split * Add instructions for node + yarn * native: fix uninstall self-destruction behavior...... by not showing the command prompt window and fork-spawning the cmd * native: deal with Unicode issues in native APIs * native: further improve Unicode support on Windows * travis: add cache and fix issues * ui: use Buefy components to... ... beautify the UI * ui: makes error message selectable * Make launcher mode behaviour more robust * Fix error display on launcher pages * Correctly handle exit on error * Bump installer version
2019-07-05 01:23:16 +00:00
// Start up the UI
frontend::launch(&app_name, is_launcher, framework);
2018-01-26 12:29:28 +00:00
}
fn replace_existing_install(current_exe: &PathBuf, installed_path: &PathBuf) -> Result<(), String> {
// Generate installer path
let platform_extension = if cfg!(windows) {
"maintenancetool.exe"
} else {
"maintenancetool"
};
let new_tool = if cfg!(windows) {
"maintenancetool_new.exe"
} else {
"maintenancetool_new"
};
if let Err(v) = fs::copy(current_exe, installed_path.join(new_tool)) {
return Err(format!("Unable to copy installer binary: {:?}", v));
}
let existing = installed_path
.join(platform_extension)
.into_os_string()
.into_string();
let new = installed_path.join(new_tool).into_os_string().into_string();
if existing.is_ok() && new.is_ok() {
// Remove NTFS alternate stream which tells the operating system that the updater was downloaded from the internet
if cfg!(windows) {
let _ = fs::remove_file(
installed_path.join("maintenancetool_new.exe:Zone.Identifier:$DATA"),
);
}
info!("Launching {:?}", existing);
let success = Command::new(new.unwrap())
.arg("--swap")
.arg(existing.unwrap())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn();
if success.is_ok() {
exit(0);
} else {
error!("Unable to start existing yuzu maintenance tool. Launching old one instead");
}
}
Ok(())
}