summaryrefslogtreecommitdiffstats
path: root/src/launcher
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2025-01-22 03:59:51 -0600
committerLibravatar bigfoot547 <[email protected]>2025-01-22 03:59:51 -0600
commit31207679094b378a2d4b35eb310f679960d6205f (patch)
tree2f750cf006ad1e5ff1bdaed908d7b6f621d018a9 /src/launcher
parentget started on downloading JREs (diff)
wip: jre download stuff
Diffstat (limited to 'src/launcher')
-rw-r--r--src/launcher/constants.rs2
-rw-r--r--src/launcher/jre.rs83
-rw-r--r--src/launcher/jre/manifest.rs31
3 files changed, 75 insertions, 41 deletions
diff --git a/src/launcher/constants.rs b/src/launcher/constants.rs
index ec7d6ba..d2f1b4f 100644
--- a/src/launcher/constants.rs
+++ b/src/launcher/constants.rs
@@ -9,7 +9,7 @@ const CRATE_NAME: &str = env!("CARGO_CRATE_NAME");
pub const USER_AGENT: &str = formatcp!("{PKG_NAME}/{PKG_VERSION} (in {CRATE_NAME})");
pub const URL_VERSION_MANIFEST: &str = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json";
pub const URL_RESOURCE_BASE: &str = "https://resources.download.minecraft.net/";
-pub const URL_JRE_MANIFEST: &str = "https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json";
+pub const URL_JRE_MANIFEST: &str = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json";
pub const NATIVES_PREFIX: &str = "natives-";
diff --git a/src/launcher/jre.rs b/src/launcher/jre.rs
index 2979c52..40fd8c1 100644
--- a/src/launcher/jre.rs
+++ b/src/launcher/jre.rs
@@ -1,8 +1,10 @@
use std::error::Error;
-use std::fmt::{Display, Formatter};
+use std::fmt::{Debug, Display, Formatter};
use std::path::{Path, PathBuf};
use log::{debug, info, warn};
-use tokio::{fs, io};
+use tokio::{fs, io, io::ErrorKind};
+use tokio::fs::File;
+use tokio::io::AsyncWriteExt;
mod arch;
mod manifest;
@@ -10,35 +12,66 @@ mod manifest;
use arch::JRE_ARCH;
use manifest::JavaRuntimesManifest;
use crate::launcher::jre::manifest::JavaRuntimeManifest;
+use crate::util;
+use crate::util::{EnsureFileError, FileVerifyError, IntegrityError};
+use crate::version::DownloadInfo;
use super::constants;
pub struct JavaRuntimeRepository {
+ online: bool,
home: PathBuf,
manifest: JavaRuntimesManifest
}
impl JavaRuntimeRepository {
- pub async fn new(home: impl AsRef<Path>) -> Result<Self, JavaRuntimeError> {
+ pub async fn new(home: impl AsRef<Path>, online: bool) -> Result<Self, JavaRuntimeError> {
info!("Java runtime architecture is \"{}\".", JRE_ARCH);
fs::create_dir_all(&home).await.map_err(|e| JavaRuntimeError::IO { what: "creating home directory", error: e })?;
- let manifest: JavaRuntimesManifest = reqwest::get(constants::URL_JRE_MANIFEST).await
- .map_err(|e| JavaRuntimeError::Download {
- what: "runtime manifest (all.json)",
- error: e
- })?.json().await
- .map_err(|e| JavaRuntimeError::Download {
- what: "runtime manifest (all.json)",
- error: e
- })?;
+ let manifest_path = home.as_ref().join("manifest.json");
+ match util::ensure_file(manifest_path.as_path(), Some(constants::URL_JRE_MANIFEST), None, None, online, true).await {
+ Ok(_) => (),
+ Err(EnsureFileError::Offline) => {
+ info!("Launcher is offline, cannot download runtime manifest.");
+ },
+ Err(e) => return Err(JavaRuntimeError::EnsureFile(e))
+ };
+
+ let manifest_file = fs::read_to_string(&manifest_path).await
+ .map_err(|e| JavaRuntimeError::IO { what: "reading runtimes manifest", error: e })?;
Ok(JavaRuntimeRepository {
+ online,
home: home.as_ref().to_path_buf(),
- manifest
+ manifest: serde_json::from_str(&manifest_file).map_err(|e| JavaRuntimeError::Deserialize { what: "runtimes manifest", error: e })?,
})
}
+ fn get_component_dir(&self, component: &str) -> PathBuf {
+ [self.home.as_path(), Path::new(JRE_ARCH), Path::new(component)].into_iter().collect()
+ }
+
+ async fn load_runtime_manifest(&self, component: &str, info: &DownloadInfo) -> Result<JavaRuntimeManifest, JavaRuntimeError> {
+ let comp_dir = self.get_component_dir(component);
+ let manifest_path = comp_dir.join("manifest.json");
+
+ debug!("Ensuring manifest for runtime {JRE_ARCH}.{component}");
+
+ fs::create_dir_all(comp_dir.as_path()).await
+ .inspect_err(|e| warn!("Failed to create directory for JRE component {}: {}", component, e))
+ .map_err(|e| JavaRuntimeError::IO { what: "creating component directory", error: e })?;
+
+ util::ensure_file(&manifest_path, info.url.as_ref().map(|s| s.as_str()), info.size, info.sha1, self.online, false).await
+ .map_err(JavaRuntimeError::EnsureFile)?;
+
+ let manifest_file = fs::read_to_string(&manifest_path).await
+ .map_err(|e| JavaRuntimeError::IO { what: "reading runtimes manifest", error: e })?;
+
+ Ok(serde_json::from_str(&manifest_file).map_err(|e| JavaRuntimeError::Deserialize { what: "runtime manifest", error: e })?)
+ }
+
+ // not very descriptive function name
pub async fn choose_runtime(&self, component: &str) -> Result<JavaRuntimeManifest, JavaRuntimeError> {
let Some(runtime_components) = self.manifest.get(JRE_ARCH) else {
return Err(JavaRuntimeError::UnsupportedArch(JRE_ARCH));
@@ -56,36 +89,33 @@ impl JavaRuntimeRepository {
return Err(JavaRuntimeError::UnsupportedComponent { arch: JRE_ARCH, component: component.to_owned() });
};
- let Some(ref url) = runtime.manifest.url else {
- return Err(JavaRuntimeError::MalformedManifest);
- };
-
- debug!("Ensuring manifest for runtime {JRE_ARCH}.{component}: {url}");
-
-
- // hmm maybe
-
- todo!()
+ self.load_runtime_manifest(component, &runtime.manifest).await
}
}
#[derive(Debug)]
pub enum JavaRuntimeError {
+ EnsureFile(EnsureFileError),
IO { what: &'static str, error: io::Error },
Download { what: &'static str, error: reqwest::Error },
+ Deserialize { what: &'static str, error: serde_json::Error },
UnsupportedArch(&'static str),
UnsupportedComponent { arch: &'static str, component: String },
- MalformedManifest
+ MalformedManifest(&'static str),
+ Integrity(IntegrityError)
}
impl Display for JavaRuntimeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
+ JavaRuntimeError::EnsureFile(e) => std::fmt::Display::fmt(e, f),
JavaRuntimeError::IO { what, error } => write!(f, "i/o error ({}): {}", what, error),
JavaRuntimeError::Download { what, error } => write!(f, "error downloading {}: {}", what, error),
+ JavaRuntimeError::Deserialize { what, error } => write!(f, "error deserializing ({what}): {error}"),
JavaRuntimeError::UnsupportedArch(arch) => write!(f, r#"unsupported architecture "{arch}""#),
JavaRuntimeError::UnsupportedComponent { arch, component } => write!(f, r#"unsupported component "{component}" for architecture "{arch}""#),
- JavaRuntimeError::MalformedManifest => f.write_str("malformed runtime manifest (launcher bug?)"),
+ JavaRuntimeError::MalformedManifest(what) => write!(f, "malformed runtime manifest: {what} (launcher bug?)"),
+ JavaRuntimeError::Integrity(e) => std::fmt::Display::fmt(e, f)
}
}
}
@@ -93,8 +123,11 @@ impl Display for JavaRuntimeError {
impl Error for JavaRuntimeError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
+ JavaRuntimeError::EnsureFile(error) => Some(error),
JavaRuntimeError::IO { error, .. } => Some(error),
JavaRuntimeError::Download { error, .. } => Some(error),
+ JavaRuntimeError::Deserialize { error, .. } => Some(error),
+ JavaRuntimeError::Integrity(error) => Some(error),
_ => None
}
}
diff --git a/src/launcher/jre/manifest.rs b/src/launcher/jre/manifest.rs
index 9b84377..ca21a2b 100644
--- a/src/launcher/jre/manifest.rs
+++ b/src/launcher/jre/manifest.rs
@@ -19,28 +19,29 @@ pub struct JavaRuntimeInfo {
// I don't see how half of this information is useful with how the JRE system currently functions -figboot
pub availability: Availability,
pub manifest: DownloadInfo,
- pub version: Version
+ //pub version: Version
}
pub type JavaRuntimesManifest = HashMap<String, HashMap<String, Vec<JavaRuntimeInfo>>>;
-#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
-#[serde(rename_all = "lowercase")]
-pub enum FileType {
- File,
- Directory,
- Link
+#[derive(Debug, Deserialize)]
+pub struct FileDownloads {
+ lzma: Option<DownloadInfo>,
+ raw: DownloadInfo
}
#[derive(Debug, Deserialize)]
-pub struct JavaRuntimeFile {
- #[serde(rename = "type")]
- pub file_type: FileType,
- #[serde(default)]
- pub executable: bool,
-
- pub lzma: DownloadInfo,
- pub raw: DownloadInfo
+#[serde(rename_all = "lowercase", tag = "type")]
+pub enum JavaRuntimeFile {
+ File {
+ #[serde(default)]
+ executable: bool,
+ downloads: FileDownloads
+ },
+ Directory,
+ Link {
+ target: String
+ }
}
#[derive(Debug, Deserialize)]