mirror of
https://github.com/yuzu-emu/liftinstall.git
synced 2024-11-22 15:15:41 +01:00
commit
137d2ec539
1389
Cargo.lock
generated
1389
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
36
Cargo.toml
36
Cargo.toml
@ -8,41 +8,41 @@ description = "An adaptable installer for your application."
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
web-view = {git = "https://github.com/Boscop/web-view.git", rev = "555f422d09cbb94e82a728d47e9e07ca91963f6e"}
|
web-view = "0.4.0"
|
||||||
|
|
||||||
hyper = "0.11.27"
|
hyper = "0.11.27"
|
||||||
futures = "*"
|
futures = "0.1.25"
|
||||||
mime_guess = "1.8.3"
|
mime_guess = "1.8.6"
|
||||||
url = "*"
|
url = "1.7.2"
|
||||||
|
|
||||||
reqwest = "0.9.0"
|
reqwest = "0.9.12"
|
||||||
number_prefix = "0.2.7"
|
number_prefix = "0.3.0"
|
||||||
|
|
||||||
serde = "1.0.27"
|
serde = "1.0.89"
|
||||||
serde_derive = "1.0.27"
|
serde_derive = "1.0.89"
|
||||||
serde_json = "1.0.9"
|
serde_json = "1.0.39"
|
||||||
|
|
||||||
toml = "0.4"
|
toml = "0.5.0"
|
||||||
|
|
||||||
semver = {version = "0.9.0", features = ["serde"]}
|
semver = {version = "0.9.0", features = ["serde"]}
|
||||||
regex = "0.2"
|
regex = "1.1.2"
|
||||||
|
|
||||||
dirs = "1.0"
|
dirs = "1.0"
|
||||||
zip = "0.4.2"
|
zip = "0.5.1"
|
||||||
xz-decom = {git = "https://github.com/j-selby/xz-decom.git", rev = "9ebf3d00d9ff909c39eec1d2cf7e6e068ce214e5"}
|
xz2 = "0.1.6"
|
||||||
tar = "0.4"
|
tar = "0.4"
|
||||||
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
fern = "0.5"
|
fern = "0.5"
|
||||||
chrono = "0.4.5"
|
chrono = "0.4.6"
|
||||||
|
|
||||||
clap = "2.32.0"
|
clap = "2.32.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
walkdir = "2"
|
walkdir = "2.2.7"
|
||||||
serde = "1.0.27"
|
serde = "1.0.89"
|
||||||
serde_derive = "1.0.27"
|
serde_derive = "1.0.89"
|
||||||
toml = "0.4"
|
toml = "0.5.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
# NFD is needed on Windows, as web-view doesn't work correctly here
|
# NFD is needed on Windows, as web-view doesn't work correctly here
|
||||||
|
@ -10,7 +10,7 @@ use std::io::Read;
|
|||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use xz_decom;
|
use xz2::read::XzDecoder;
|
||||||
|
|
||||||
pub trait Archive<'a> {
|
pub trait Archive<'a> {
|
||||||
/// func: iterator value, max size, file name, file contents
|
/// func: iterator value, max size, file name, file contents
|
||||||
@ -92,8 +92,10 @@ pub fn read_archive<'a>(name: &str, data: &'a [u8]) -> Result<Box<Archive<'a> +
|
|||||||
Ok(Box::new(ZipArchive { archive }))
|
Ok(Box::new(ZipArchive { archive }))
|
||||||
} else if name.ends_with(".tar.xz") {
|
} else if name.ends_with(".tar.xz") {
|
||||||
// Decompress a .tar.xz file
|
// Decompress a .tar.xz file
|
||||||
let decompressed_data = xz_decom::decompress(data)
|
let mut decompresser = XzDecoder::new(data);
|
||||||
.map_err(|x| format!("Failed to build decompressor: {:?}", x))?;
|
let mut decompressed_data = Vec::new();
|
||||||
|
decompresser.read_to_end(&mut decompressed_data)
|
||||||
|
.map_err(|x| format!("Failed to decompress data: {:?}", x))?;
|
||||||
|
|
||||||
let decompressed_contents: Box<Read> = Box::new(Cursor::new(decompressed_data));
|
let decompressed_contents: Box<Read> = Box::new(Cursor::new(decompressed_data));
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ use std::fs::remove_file;
|
|||||||
|
|
||||||
use http;
|
use http;
|
||||||
|
|
||||||
use number_prefix::{decimal_prefix, Prefixed, Standalone};
|
use number_prefix::{NumberPrefix, Prefixed, Standalone};
|
||||||
|
|
||||||
/// A message thrown during the installation of packages.
|
/// A message thrown during the installation of packages.
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -264,11 +264,11 @@ impl InstallerFramework {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Pretty print data volumes
|
// Pretty print data volumes
|
||||||
let pretty_current = match decimal_prefix(downloaded as f64) {
|
let pretty_current = match NumberPrefix::decimal(downloaded as f64) {
|
||||||
Standalone(bytes) => format!("{} bytes", bytes),
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
};
|
};
|
||||||
let pretty_total = match decimal_prefix(size as f64) {
|
let pretty_total = match NumberPrefix::decimal(size as f64) {
|
||||||
Standalone(bytes) => format!("{} bytes", bytes),
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
};
|
};
|
||||||
@ -328,7 +328,8 @@ impl InstallerFramework {
|
|||||||
x.to_str()
|
x.to_str()
|
||||||
.log_expect("Unable to convert argument to String")
|
.log_expect("Unable to convert argument to String")
|
||||||
.to_string()
|
.to_string()
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
{
|
{
|
||||||
let new_app_file = match File::create(&args_file) {
|
let new_app_file = match File::create(&args_file) {
|
||||||
|
@ -17,7 +17,8 @@ pub fn setup_logger(file_name: String) -> Result<(), fern::InitError> {
|
|||||||
record.level(),
|
record.level(),
|
||||||
message
|
message
|
||||||
))
|
))
|
||||||
}).level(log::LevelFilter::Info)
|
})
|
||||||
|
.level(log::LevelFilter::Info)
|
||||||
.chain(io::stdout())
|
.chain(io::stdout())
|
||||||
.chain(fern::log_file(file_name)?)
|
.chain(fern::log_file(file_name)?)
|
||||||
.apply()?;
|
.apply()?;
|
||||||
|
46
src/main.rs
46
src/main.rs
@ -30,7 +30,7 @@ extern crate semver;
|
|||||||
|
|
||||||
extern crate dirs;
|
extern crate dirs;
|
||||||
extern crate tar;
|
extern crate tar;
|
||||||
extern crate xz_decom;
|
extern crate xz2;
|
||||||
extern crate zip;
|
extern crate zip;
|
||||||
|
|
||||||
extern crate fern;
|
extern crate fern;
|
||||||
@ -40,7 +40,7 @@ extern crate log;
|
|||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
|
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
#[cfg(windows)]
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
|
|
||||||
mod archives;
|
mod archives;
|
||||||
@ -112,7 +112,8 @@ fn main() {
|
|||||||
.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),
|
||||||
).arg(
|
)
|
||||||
|
.arg(
|
||||||
Arg::with_name("swap")
|
Arg::with_name("swap")
|
||||||
.long("swap")
|
.long("swap")
|
||||||
.value_name("TARGET")
|
.value_name("TARGET")
|
||||||
@ -280,14 +281,15 @@ fn main() {
|
|||||||
let resizable = false;
|
let resizable = false;
|
||||||
let debug = true;
|
let debug = true;
|
||||||
|
|
||||||
run(
|
web_view::builder()
|
||||||
&format!("{} Installer", app_name),
|
.title(&format!("{} Installer", app_name))
|
||||||
Content::Url(http_address),
|
.content(Content::Url(http_address))
|
||||||
Some(size),
|
.size(size.0, size.1)
|
||||||
resizable,
|
.resizable(resizable)
|
||||||
debug,
|
.debug(debug)
|
||||||
|_| {},
|
.user_data(())
|
||||||
|wv, msg, _| {
|
.invoke_handler(|wv, msg| {
|
||||||
|
let mut cb_result = Ok(());
|
||||||
let command: CallbackType =
|
let command: CallbackType =
|
||||||
serde_json::from_str(msg).log_expect(&format!("Unable to parse string: {:?}", msg));
|
serde_json::from_str(msg).log_expect(&format!("Unable to parse string: {:?}", msg));
|
||||||
|
|
||||||
@ -299,20 +301,21 @@ fn main() {
|
|||||||
let result = match nfd::open_pick_folder(None)
|
let result = match nfd::open_pick_folder(None)
|
||||||
.log_expect("Unable to open folder dialog")
|
.log_expect("Unable to open folder dialog")
|
||||||
{
|
{
|
||||||
Response::Okay(v) => v,
|
Response::Okay(v) => Ok(v),
|
||||||
_ => return,
|
_ => Err(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let result =
|
let result = wv
|
||||||
wv.dialog(Dialog::ChooseDirectory, "Select a install directory...", "");
|
.dialog()
|
||||||
|
.choose_directory("Select a install directory...", "");
|
||||||
|
|
||||||
if !result.is_empty() {
|
if result.is_ok() {
|
||||||
let result = serde_json::to_string(&result)
|
let result = serde_json::to_string(&result.ok())
|
||||||
.log_expect("Unable to serialize response");
|
.log_expect("Unable to serialize response");
|
||||||
let command = format!("{}({});", callback_name, result);
|
let command = format!("{}({});", callback_name, result);
|
||||||
debug!("Injecting response: {}", command);
|
debug!("Injecting response: {}", command);
|
||||||
wv.eval(&command);
|
cb_result = wv.eval(&command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallbackType::Log { msg, kind } => {
|
CallbackType::Log { msg, kind } => {
|
||||||
@ -326,7 +329,8 @@ fn main() {
|
|||||||
log!(target: "liftinstall::frontend-js", kind, "{}", msg);
|
log!(target: "liftinstall::frontend-js", kind, "{}", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
cb_result
|
||||||
(),
|
})
|
||||||
);
|
.run()
|
||||||
|
.expect("Unable to launch Web UI!");
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
/// Basic definition of some running process.
|
/// Basic definition of some running process.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
pub pid : usize,
|
pub pid: usize,
|
||||||
pub name : String
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -23,14 +23,13 @@ mod natives {
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use winapi::shared::minwindef::{DWORD, FALSE, MAX_PATH};
|
use winapi::shared::minwindef::{DWORD, FALSE, MAX_PATH};
|
||||||
|
use winapi::um::processthreadsapi::OpenProcess;
|
||||||
|
use winapi::um::psapi::{
|
||||||
|
EnumProcessModulesEx, GetModuleFileNameExW, K32EnumProcesses, LIST_MODULES_ALL,
|
||||||
|
};
|
||||||
use winapi::um::winnt::{
|
use winapi::um::winnt::{
|
||||||
HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ,
|
HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ,
|
||||||
};
|
};
|
||||||
use winapi::um::processthreadsapi::{OpenProcess};
|
|
||||||
use winapi::um::psapi::{
|
|
||||||
K32EnumProcesses,
|
|
||||||
EnumProcessModulesEx, GetModuleFileNameExW, LIST_MODULES_ALL,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn saveShortcut(
|
pub fn saveShortcut(
|
||||||
@ -149,9 +148,7 @@ mod natives {
|
|||||||
|
|
||||||
let size = ::std::mem::size_of::<DWORD>() * process_ids.len();
|
let size = ::std::mem::size_of::<DWORD>() * process_ids.len();
|
||||||
unsafe {
|
unsafe {
|
||||||
if K32EnumProcesses(process_ids.as_mut_ptr(),
|
if K32EnumProcesses(process_ids.as_mut_ptr(), size as DWORD, &mut cb_needed) == 0 {
|
||||||
size as DWORD,
|
|
||||||
&mut cb_needed) == 0 {
|
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +157,7 @@ mod natives {
|
|||||||
|
|
||||||
let mut processes = Vec::new();
|
let mut processes = Vec::new();
|
||||||
|
|
||||||
for i in 0 .. nb_processes {
|
for i in 0..nb_processes {
|
||||||
let pid = process_ids[i as usize];
|
let pid = process_ids[i as usize];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -169,20 +166,25 @@ mod natives {
|
|||||||
let mut process_name = [0u16; MAX_PATH + 1];
|
let mut process_name = [0u16; MAX_PATH + 1];
|
||||||
let mut cb_needed = 0;
|
let mut cb_needed = 0;
|
||||||
|
|
||||||
if EnumProcessModulesEx(process_handler,
|
if EnumProcessModulesEx(
|
||||||
&mut h_mod,
|
process_handler,
|
||||||
::std::mem::size_of::<DWORD>() as DWORD,
|
&mut h_mod,
|
||||||
&mut cb_needed,
|
::std::mem::size_of::<DWORD>() as DWORD,
|
||||||
LIST_MODULES_ALL) != 0 {
|
&mut cb_needed,
|
||||||
GetModuleFileNameExW(process_handler,
|
LIST_MODULES_ALL,
|
||||||
h_mod,
|
) != 0
|
||||||
process_name.as_mut_ptr(),
|
{
|
||||||
MAX_PATH as DWORD + 1);
|
GetModuleFileNameExW(
|
||||||
|
process_handler,
|
||||||
|
h_mod,
|
||||||
|
process_name.as_mut_ptr(),
|
||||||
|
MAX_PATH as DWORD + 1,
|
||||||
|
);
|
||||||
|
|
||||||
let mut pos = 0;
|
let mut pos = 0;
|
||||||
for x in process_name.iter() {
|
for x in process_name.iter() {
|
||||||
if *x == 0 {
|
if *x == 0 {
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
@ -210,11 +212,11 @@ mod natives {
|
|||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
pub fn create_shortcut(
|
pub fn create_shortcut(
|
||||||
name: &str,
|
_name: &str,
|
||||||
description: &str,
|
_description: &str,
|
||||||
target: &str,
|
_target: &str,
|
||||||
args: &str,
|
_args: &str,
|
||||||
working_dir: &str,
|
_working_dir: &str,
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
// TODO: no-op
|
// TODO: no-op
|
||||||
warn!("create_shortcut is stubbed!");
|
warn!("create_shortcut is stubbed!");
|
||||||
|
@ -62,7 +62,8 @@ impl WebServer {
|
|||||||
Ok(WebService {
|
Ok(WebService {
|
||||||
framework: framework.clone(),
|
framework: framework.clone(),
|
||||||
})
|
})
|
||||||
}).log_expect("Failed to bind to port");
|
})
|
||||||
|
.log_expect("Failed to bind to port");
|
||||||
|
|
||||||
server.run().log_expect("Failed to run HTTP server");
|
server.run().log_expect("Failed to run HTTP server");
|
||||||
});
|
});
|
||||||
|
@ -41,7 +41,8 @@ impl ReleaseSource for GithubReleases {
|
|||||||
.get(&format!(
|
.get(&format!(
|
||||||
"https://api.github.com/repos/{}/releases",
|
"https://api.github.com/repos/{}/releases",
|
||||||
config.repo
|
config.repo
|
||||||
)).header(USER_AGENT, "liftinstall (j-selby)")
|
))
|
||||||
|
.header(USER_AGENT, "liftinstall (j-selby)")
|
||||||
.send()
|
.send()
|
||||||
.map_err(|x| format!("Error while sending HTTP request: {:?}", x))?;
|
.map_err(|x| format!("Error while sending HTTP request: {:?}", x))?;
|
||||||
|
|
||||||
@ -87,14 +88,16 @@ impl ReleaseSource for GithubReleases {
|
|||||||
let string = match asset["name"].as_str() {
|
let string = match asset["name"].as_str() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
return Err("JSON payload missing information about release name".to_string())
|
return Err(
|
||||||
|
"JSON payload missing information about release name".to_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let url = match asset["browser_download_url"].as_str() {
|
let url = match asset["browser_download_url"].as_str() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
return Err("JSON payload missing information about release URL".to_string())
|
return Err("JSON payload missing information about release URL".to_string());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use tasks::resolver::ResolvePackageTask;
|
|||||||
|
|
||||||
use http::stream_file;
|
use http::stream_file;
|
||||||
|
|
||||||
use number_prefix::{decimal_prefix, Prefixed, Standalone};
|
use number_prefix::{NumberPrefix, Prefixed, Standalone};
|
||||||
|
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
|
|
||||||
@ -68,11 +68,11 @@ impl Task for DownloadPackageTask {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Pretty print data volumes
|
// Pretty print data volumes
|
||||||
let pretty_current = match decimal_prefix(downloaded as f64) {
|
let pretty_current = match NumberPrefix::decimal(downloaded as f64) {
|
||||||
Standalone(bytes) => format!("{} bytes", bytes),
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
};
|
};
|
||||||
let pretty_total = match decimal_prefix(size as f64) {
|
let pretty_total = match NumberPrefix::decimal(size as f64) {
|
||||||
Standalone(bytes) => format!("{} bytes", bytes),
|
Standalone(bytes) => format!("{} bytes", bytes),
|
||||||
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
|
||||||
};
|
};
|
||||||
|
@ -7,8 +7,8 @@ use tasks::TaskDependency;
|
|||||||
use tasks::TaskMessage;
|
use tasks::TaskMessage;
|
||||||
use tasks::TaskParamType;
|
use tasks::TaskParamType;
|
||||||
|
|
||||||
use native::Process;
|
|
||||||
use native::get_process_names;
|
use native::get_process_names;
|
||||||
|
use native::Process;
|
||||||
|
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ impl Task for EnsureOnlyInstanceTask {
|
|||||||
) -> Result<TaskParamType, String> {
|
) -> Result<TaskParamType, String> {
|
||||||
assert_eq!(input.len(), 0);
|
assert_eq!(input.len(), 0);
|
||||||
|
|
||||||
let current_pid = process::id() as usize;
|
let current_pid = process::id() as usize;
|
||||||
for Process { pid, name } in get_process_names() {
|
for Process { pid, name } in get_process_names() {
|
||||||
if pid == current_pid {
|
if pid == current_pid {
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user