mirror of
https://github.com/yuzu-emu/liftinstall.git
synced 2024-12-22 19:25:40 +00:00
Add a global shortcut for the maintenance tool
This commit is contained in:
parent
82b3681a74
commit
19bec5d80c
|
@ -27,6 +27,7 @@ use logging::LoggingErrors;
|
|||
use dirs::home_dir;
|
||||
|
||||
use std::fs::remove_file;
|
||||
use tasks::uninstall_global_shortcut::UninstallGlobalShortcutsTask;
|
||||
|
||||
/// A message thrown during the installation of packages.
|
||||
#[derive(Serialize)]
|
||||
|
@ -36,12 +37,29 @@ pub enum InstallMessage {
|
|||
EOF,
|
||||
}
|
||||
|
||||
/// Metadata about the current installation itself.
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct InstallationDatabase {
|
||||
pub packages: Vec<LocalInstallation>,
|
||||
pub shortcuts: Vec<String>,
|
||||
}
|
||||
|
||||
impl InstallationDatabase {
|
||||
/// Creates a new, empty installation database.
|
||||
pub fn new() -> InstallationDatabase {
|
||||
InstallationDatabase {
|
||||
packages: Vec::new(),
|
||||
shortcuts: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The installer framework contains metadata about packages, what is installable, what isn't,
|
||||
/// etc.
|
||||
pub struct InstallerFramework {
|
||||
pub base_attributes: BaseAttributes,
|
||||
pub config: Option<Config>,
|
||||
pub database: Vec<LocalInstallation>,
|
||||
pub database: InstallationDatabase,
|
||||
pub install_path: Option<PathBuf>,
|
||||
pub preexisting_install: bool,
|
||||
pub is_launcher: bool,
|
||||
|
@ -51,7 +69,7 @@ pub struct InstallerFramework {
|
|||
/// Contains basic properties on the status of the session. Subset of InstallationFramework.
|
||||
#[derive(Serialize)]
|
||||
pub struct InstallationStatus {
|
||||
pub database: Vec<LocalInstallation>,
|
||||
pub database: InstallationDatabase,
|
||||
pub install_path: Option<String>,
|
||||
pub preexisting_install: bool,
|
||||
pub is_launcher: bool,
|
||||
|
@ -110,7 +128,7 @@ impl InstallerFramework {
|
|||
// Calculate packages to *uninstall*
|
||||
let mut uninstall_items = Vec::new();
|
||||
if !fresh_install {
|
||||
for package in &self.database {
|
||||
for package in &self.database.packages {
|
||||
if !items.contains(&package.name) {
|
||||
uninstall_items.push(package.name.clone());
|
||||
}
|
||||
|
@ -141,7 +159,12 @@ impl InstallerFramework {
|
|||
|
||||
/// Sends a request for everything to be uninstalled.
|
||||
pub fn uninstall(&mut self, messages: &Sender<InstallMessage>) -> Result<(), String> {
|
||||
let items: Vec<String> = self.database.iter().map(|x| x.name.clone()).collect();
|
||||
let items: Vec<String> = self
|
||||
.database
|
||||
.packages
|
||||
.iter()
|
||||
.map(|x| x.name.clone())
|
||||
.collect();
|
||||
|
||||
let task = Box::new(UninstallTask { items });
|
||||
|
||||
|
@ -155,6 +178,17 @@ impl InstallerFramework {
|
|||
}
|
||||
}).map(|_x| ())?;
|
||||
|
||||
// Uninstall shortcuts
|
||||
let task = Box::new(UninstallGlobalShortcutsTask {});
|
||||
|
||||
let mut tree = DependencyTree::build(task);
|
||||
|
||||
tree.execute(self, &|msg: &str, progress: f64| {
|
||||
if let Err(v) = messages.send(InstallMessage::Status(msg.to_string(), progress as _)) {
|
||||
error!("Failed to submit queue message: {:?}", v);
|
||||
}
|
||||
}).map(|_x| ())?;
|
||||
|
||||
// Delete the metadata file
|
||||
let path = self
|
||||
.install_path
|
||||
|
@ -216,7 +250,7 @@ impl InstallerFramework {
|
|||
InstallerFramework {
|
||||
base_attributes: attrs,
|
||||
config: None,
|
||||
database: Vec::new(),
|
||||
database: InstallationDatabase::new(),
|
||||
install_path: None,
|
||||
preexisting_install: false,
|
||||
is_launcher: false,
|
||||
|
@ -234,7 +268,7 @@ impl InstallerFramework {
|
|||
Err(v) => return Err(format!("Unable to open file handle: {:?}", v)),
|
||||
};
|
||||
|
||||
let database: Vec<LocalInstallation> = match serde_json::from_reader(metadata_file) {
|
||||
let database: InstallationDatabase = match serde_json::from_reader(metadata_file) {
|
||||
Ok(v) => v,
|
||||
Err(v) => return Err(format!("Unable to read metadata file: {:?}", v)),
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ impl Task for DownloadPackageTask {
|
|||
};
|
||||
|
||||
// Check to see if this is the newest file available already
|
||||
for element in &context.database {
|
||||
for element in &context.database.packages {
|
||||
if element.name == self.name {
|
||||
if element.version == version {
|
||||
info!("{:?} is already up to date.", self.name);
|
||||
|
|
|
@ -7,6 +7,7 @@ use tasks::install_pkg::InstallPackageTask;
|
|||
use tasks::save_executable::SaveExecutableTask;
|
||||
use tasks::uninstall_pkg::UninstallPackageTask;
|
||||
|
||||
use tasks::install_global_shortcut::InstallGlobalShortcutsTask;
|
||||
use tasks::Task;
|
||||
use tasks::TaskDependency;
|
||||
use tasks::TaskOrdering;
|
||||
|
@ -61,6 +62,11 @@ impl Task for InstallTask {
|
|||
TaskOrdering::Pre,
|
||||
Box::new(SaveExecutableTask {}),
|
||||
));
|
||||
|
||||
elements.push(TaskDependency::build(
|
||||
TaskOrdering::Pre,
|
||||
Box::new(InstallGlobalShortcutsTask {}),
|
||||
));
|
||||
}
|
||||
|
||||
elements
|
||||
|
|
72
src/tasks/install_global_shortcut.rs
Normal file
72
src/tasks/install_global_shortcut.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
//! Generates the global shortcut for this application.
|
||||
|
||||
use installer::InstallerFramework;
|
||||
|
||||
use tasks::Task;
|
||||
use tasks::TaskDependency;
|
||||
use tasks::TaskParamType;
|
||||
|
||||
use logging::LoggingErrors;
|
||||
|
||||
use native::create_shortcut;
|
||||
use tasks::save_database::SaveDatabaseTask;
|
||||
use tasks::TaskOrdering;
|
||||
|
||||
pub struct InstallGlobalShortcutsTask {}
|
||||
|
||||
impl Task for InstallGlobalShortcutsTask {
|
||||
fn execute(
|
||||
&mut self,
|
||||
_: Vec<TaskParamType>,
|
||||
context: &mut InstallerFramework,
|
||||
messenger: &Fn(&str, f64),
|
||||
) -> Result<TaskParamType, String> {
|
||||
messenger(&format!("Generating global shortcut..."), 0.0);
|
||||
|
||||
let path = context
|
||||
.install_path
|
||||
.as_ref()
|
||||
.log_expect("No install path specified");
|
||||
|
||||
let starting_dir = path
|
||||
.to_str()
|
||||
.log_expect("Unable to build shortcut metadata (startingdir)");
|
||||
|
||||
// Generate installer path
|
||||
let platform_extension = if cfg!(windows) {
|
||||
"maintenancetool.exe"
|
||||
} else {
|
||||
"maintenancetool"
|
||||
};
|
||||
|
||||
let tool_path = path.join(platform_extension);
|
||||
let tool_path = tool_path
|
||||
.to_str()
|
||||
.log_expect("Unable to build shortcut metadata (tool)");
|
||||
|
||||
context.database.shortcuts.push(create_shortcut(
|
||||
&format!("{} maintenance tool", context.base_attributes.name),
|
||||
&format!(
|
||||
"Launch the {} maintenance tool to update, modify and uninstall the application.",
|
||||
context.base_attributes.name
|
||||
),
|
||||
tool_path,
|
||||
// TODO: Send by list
|
||||
"",
|
||||
&starting_dir,
|
||||
)?);
|
||||
|
||||
Ok(TaskParamType::None)
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<TaskDependency> {
|
||||
vec![TaskDependency::build(
|
||||
TaskOrdering::Post,
|
||||
Box::new(SaveDatabaseTask {}),
|
||||
)]
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"InstallGlobalShortcutsTask".to_string()
|
||||
}
|
||||
}
|
|
@ -163,7 +163,7 @@ impl Task for InstallPackageTask {
|
|||
})?;
|
||||
|
||||
// Save metadata about this package
|
||||
context.database.push(LocalInstallation {
|
||||
context.database.packages.push(LocalInstallation {
|
||||
name: package.name.to_owned(),
|
||||
version,
|
||||
shortcuts,
|
||||
|
|
|
@ -12,12 +12,14 @@ use sources::types::Version;
|
|||
pub mod download_pkg;
|
||||
pub mod install;
|
||||
pub mod install_dir;
|
||||
pub mod install_global_shortcut;
|
||||
pub mod install_pkg;
|
||||
pub mod install_shortcuts;
|
||||
pub mod resolver;
|
||||
pub mod save_database;
|
||||
pub mod save_executable;
|
||||
pub mod uninstall;
|
||||
pub mod uninstall_global_shortcut;
|
||||
pub mod uninstall_pkg;
|
||||
pub mod uninstall_shortcuts;
|
||||
|
||||
|
|
44
src/tasks/uninstall_global_shortcut.rs
Normal file
44
src/tasks/uninstall_global_shortcut.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
//! Uninstalls a specific package.
|
||||
|
||||
use installer::InstallerFramework;
|
||||
|
||||
use tasks::Task;
|
||||
use tasks::TaskDependency;
|
||||
use tasks::TaskParamType;
|
||||
|
||||
use std::fs::remove_file;
|
||||
use tasks::save_database::SaveDatabaseTask;
|
||||
use tasks::TaskOrdering;
|
||||
|
||||
pub struct UninstallGlobalShortcutsTask {}
|
||||
|
||||
impl Task for UninstallGlobalShortcutsTask {
|
||||
fn execute(
|
||||
&mut self,
|
||||
input: Vec<TaskParamType>,
|
||||
context: &mut InstallerFramework,
|
||||
messenger: &Fn(&str, f64),
|
||||
) -> Result<TaskParamType, String> {
|
||||
assert_eq!(input.len(), 0);
|
||||
|
||||
messenger(&format!("Uninstalling global shortcut..."), 0.0);
|
||||
|
||||
while let Some(file) = context.database.shortcuts.pop() {
|
||||
info!("Deleting shortcut {:?}", file);
|
||||
remove_file(file).map_err(|x| format!("Unable to delete global shortcut: {:?}", x))?;
|
||||
}
|
||||
|
||||
Ok(TaskParamType::None)
|
||||
}
|
||||
|
||||
fn dependencies(&self) -> Vec<TaskDependency> {
|
||||
vec![TaskDependency::build(
|
||||
TaskOrdering::Post,
|
||||
Box::new(SaveDatabaseTask {}),
|
||||
)]
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"UninstallGlobalShortcutsTask".to_string()
|
||||
}
|
||||
}
|
|
@ -36,9 +36,9 @@ impl Task for UninstallPackageTask {
|
|||
.log_expect("No install path specified");
|
||||
|
||||
let mut metadata: Option<LocalInstallation> = None;
|
||||
for i in 0..context.database.len() {
|
||||
if self.name == context.database[i].name {
|
||||
metadata = Some(context.database.remove(i));
|
||||
for i in 0..context.database.packages.len() {
|
||||
if self.name == context.database.packages[i].name {
|
||||
metadata = Some(context.database.packages.remove(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@ impl Task for UninstallShortcutsTask {
|
|||
.log_expect("No install path specified");
|
||||
|
||||
let mut metadata: Option<LocalInstallation> = None;
|
||||
for i in 0..context.database.len() {
|
||||
if self.name == context.database[i].name {
|
||||
metadata = Some(context.database[i].clone());
|
||||
for i in 0..context.database.packages.len() {
|
||||
if self.name == context.database.packages[i].name {
|
||||
metadata = Some(context.database.packages[i].clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ impl Task for UninstallShortcutsTask {
|
|||
for (i, file) in package.shortcuts.iter().enumerate() {
|
||||
let name = file.clone();
|
||||
let file = path.join(file);
|
||||
info!("Deleting {:?}", file);
|
||||
info!("Deleting shortcut {:?}", file);
|
||||
|
||||
messenger(
|
||||
&format!("Deleting {} ({} of {})", name, i + 1, max),
|
||||
&format!("Deleting shortcut {} ({} of {})", name, i + 1, max),
|
||||
(i as f64) / (max as f64),
|
||||
);
|
||||
|
||||
|
@ -80,7 +80,7 @@ impl Task for UninstallShortcutsTask {
|
|||
};
|
||||
|
||||
if let Err(v) = result {
|
||||
error!("Failed to delete file: {:?}", v);
|
||||
error!("Failed to delete shortcut: {:?}", v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,10 @@ const DownloadConfig = {
|
|||
app.config.packages[x].installed = false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < app.metadata.database.length; i++) {
|
||||
for (var i = 0; i < app.metadata.database.packages.length; i++) {
|
||||
// Find this config package
|
||||
for (var x = 0; x < app.config.packages.length; x++) {
|
||||
if (app.config.packages[x].name === app.metadata.database[i].name) {
|
||||
if (app.config.packages[x].name === app.metadata.database.packages[i].name) {
|
||||
app.config.packages[x].default = true;
|
||||
app.config.packages[x].installed = true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue