This is v2 of OneClient. Removed all web-related stuff. Co-Authored-By: Julian Chang <wyvest@polyfrost.org>
136 lines
3.7 KiB
Rust
136 lines
3.7 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
use reqwest::Method;
|
|
use tracing::instrument;
|
|
use url::Url;
|
|
|
|
use crate::http::{ResponseNotifyOptions, ResponseOptions};
|
|
use crate::java::data::{
|
|
java_executable_relative_path, JavaPackage, PackageArchive,
|
|
};
|
|
use crate::paths;
|
|
use crate::state::LauncherServices;
|
|
use crate::LauncherResult;
|
|
|
|
#[instrument(skip(services))]
|
|
pub async fn install_package(
|
|
package: &JavaPackage,
|
|
services: &LauncherServices,
|
|
) -> LauncherResult<PathBuf> {
|
|
let java_dir = paths::java_dir()?;
|
|
polyio::create_dir_all(&java_dir).await?;
|
|
|
|
let archive_path = java_dir.join(polyio::sanitize_path(&package.name));
|
|
|
|
services.requester
|
|
.download_file(
|
|
reqwest::Request::new(Method::GET, Url::parse(&package.download_url)?),
|
|
&archive_path,
|
|
ResponseOptions {
|
|
notify: Some(ResponseNotifyOptions::standalone(format!(
|
|
"Installing {} {}",
|
|
package.vendor,
|
|
package.java_version.first().copied().unwrap_or(0)
|
|
))),
|
|
},
|
|
services,
|
|
)
|
|
.await?;
|
|
|
|
let extract_root = java_dir.join(stem_without_archive(&package.name));
|
|
|
|
match package.archive {
|
|
PackageArchive::Zip => polyio::extract_zip(&archive_path, &extract_root).await?,
|
|
PackageArchive::TarGz => polyio::extract_tar_gz(&archive_path, &extract_root).await?,
|
|
}
|
|
|
|
let executable = resolve_installed_executable(&extract_root, package);
|
|
|
|
#[cfg(unix)]
|
|
{
|
|
let _ = tokio::process::Command::new("chmod")
|
|
.arg("755")
|
|
.arg(&executable)
|
|
.output()
|
|
.await;
|
|
}
|
|
|
|
let _ = tokio::fs::remove_file(&archive_path).await;
|
|
|
|
Ok(executable)
|
|
}
|
|
|
|
#[instrument]
|
|
fn resolve_installed_executable(extract_root: &Path, package: &JavaPackage) -> PathBuf {
|
|
let mut base_path = extract_root.to_path_buf();
|
|
|
|
if let Ok(entries) = std::fs::read_dir(extract_root) {
|
|
let valid_dirs: Vec<PathBuf> = entries
|
|
.flatten()
|
|
.filter(|e| e.file_type().map(|t| t.is_dir()).unwrap_or(false))
|
|
.map(|e| e.path())
|
|
.collect();
|
|
|
|
if valid_dirs.len() == 1 {
|
|
base_path = valid_dirs[0].clone();
|
|
}
|
|
}
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
{
|
|
let _ = package;
|
|
let subfolder_exec = base_path.join(java_executable_relative_path());
|
|
if subfolder_exec.exists() {
|
|
subfolder_exec
|
|
} else {
|
|
extract_root.join(java_executable_relative_path())
|
|
}
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
use crate::java::vendors::JavaVendor;
|
|
|
|
if !base_path.join("Contents").join("Home").exists() {
|
|
if let Ok(mut entries) = std::fs::read_dir(&base_path) {
|
|
if let Some(dir) = entries.flatten().find(|entry| {
|
|
let file_name = entry.file_name();
|
|
let name = file_name.to_string_lossy();
|
|
(name.ends_with(".jre") || name.ends_with(".jdk") || name.contains("zulu"))
|
|
&& entry.path().join("Contents").join("Home").exists()
|
|
}) {
|
|
base_path = dir.path();
|
|
}
|
|
}
|
|
}
|
|
|
|
if package.vendor == JavaVendor::Zulu {
|
|
if let Some(major) = package.java_version.first() {
|
|
let zulu_bundle = base_path.join(format!("zulu-{major}.jre"));
|
|
if zulu_bundle.join("Contents").join("Home").exists() {
|
|
base_path = zulu_bundle;
|
|
}
|
|
}
|
|
}
|
|
|
|
base_path.join(java_executable_relative_path())
|
|
}
|
|
}
|
|
|
|
fn stem_without_archive(name: &str) -> String {
|
|
let path = std::path::Path::new(name);
|
|
let stem = path
|
|
.file_stem()
|
|
.and_then(|s| s.to_str())
|
|
.unwrap_or(name);
|
|
|
|
if stem.ends_with(".tar") {
|
|
std::path::Path::new(stem)
|
|
.file_stem()
|
|
.and_then(|s| s.to_str())
|
|
.map(String::from)
|
|
.unwrap_or_else(|| stem.to_string())
|
|
} else {
|
|
stem.to_string()
|
|
}
|
|
}
|