From 12b9f45508f5f52e470416ce2e519b1c827c5db1 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Fri, 7 Feb 2025 03:55:59 -0600 Subject: finish up changes now just need to finish the command --- ozone-cli/src/main.rs | 2 +- ozone/src/launcher.rs | 12 +----- ozone/src/launcher/settings.rs | 2 +- ozone/src/launcher/version.rs | 86 ++++++++++++++++++++++-------------------- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/ozone-cli/src/main.rs b/ozone-cli/src/main.rs index d18e9b8..adfeb71 100644 --- a/ozone-cli/src/main.rs +++ b/ozone-cli/src/main.rs @@ -5,7 +5,7 @@ use std::process::ExitCode; use log::{error, info, trace}; use clap::Parser; use ozone::launcher::{Launcher, Settings}; - +use ozone::launcher::version::VersionList; use crate::cli::{Cli, ProfileCommand, RootCommand}; async fn main_inner(cli: Cli) -> Result> { diff --git a/ozone/src/launcher.rs b/ozone/src/launcher.rs index 0916fd8..6feeab5 100644 --- a/ozone/src/launcher.rs +++ b/ozone/src/launcher.rs @@ -260,11 +260,7 @@ impl Launcher { let versions_home = home.join("versions"); debug!("Version list online?: {online}"); - let versions = if online { - VersionList::online(versions_home.as_ref()).await.map_err(LaunchError::VersionInit)? - } else { - VersionList::offline(versions_home.as_ref()).await.map_err(LaunchError::VersionInit)? - }; + let versions = VersionList::new(&versions_home, online).await.map_err(LaunchError::VersionInit)?; let assets_path = home.join("assets"); @@ -337,11 +333,7 @@ impl Launcher { let feature_matcher = ProfileFeatureMatcher { profile }; let version_id = profile.get_version(); - let Some(version_id) = self.versions.get_profile_version_id(version_id) else { - // idk how common this use case actually is - warn!("Can't use latest release/snapshot profiles while offline!"); - return Err(LaunchError::UnknownVersion("".into())); - }; + let version_id = self.versions.get_profile_version_id(version_id); info!("Preparing launch for \"{}\"...", version_id); diff --git a/ozone/src/launcher/settings.rs b/ozone/src/launcher/settings.rs index c9f2dd5..c480c33 100644 --- a/ozone/src/launcher/settings.rs +++ b/ozone/src/launcher/settings.rs @@ -31,7 +31,7 @@ pub struct SettingsData { impl SettingsData { fn check_consistent(&self) -> Result<(), String> { - if let Some((name, profile)) = self.profiles.iter().find(|(name, profile)| !self.instances.contains_key(&profile.instance)) { + if let Some((name, profile)) = self.profiles.iter().find(|(_, profile)| !self.instances.contains_key(&profile.instance)) { return Err(format!("profile {} refers to instance {}, which does not exist.", name, &profile.instance)); } diff --git a/ozone/src/launcher/version.rs b/ozone/src/launcher/version.rs index c7268db..a5369b9 100644 --- a/ozone/src/launcher/version.rs +++ b/ozone/src/launcher/version.rs @@ -1,10 +1,9 @@ use std::{collections::{BTreeMap, HashMap}, error::Error, io::ErrorKind}; use std::borrow::Cow; use std::collections::HashSet; -use std::fmt::Display; +use std::fmt::{Display, Write}; use std::path::{Path, PathBuf}; use chrono::{DateTime, TimeDelta, Utc}; -use futures::TryFutureExt; use log::{debug, info, warn}; use serde::{Deserialize, Serialize}; use sha1_smol::{Digest, Sha1}; @@ -20,7 +19,8 @@ pub enum VersionError { IO { what: String, error: io::Error }, Request { what: String, error: reqwest::Error }, MalformedObject { what: String, error: serde_json::Error }, - VersionIntegrity { id: String, expect: Digest, got: Digest } + VersionIntegrity { id: String, expect: Digest, got: Digest }, + Offline } impl Display for VersionError { @@ -29,7 +29,8 @@ impl Display for VersionError { VersionError::IO { what, error } => write!(f, "i/o error ({what}): {error}"), VersionError::Request { what, error } => write!(f, "request error ({what}): {error}"), VersionError::MalformedObject { what, error } => write!(f, "malformed {what}: {error}"), - VersionError::VersionIntegrity { id, expect, got } => write!(f, "version {id} integrity mismatch (expect {expect}, got {got})") + VersionError::VersionIntegrity { id, expect, got } => write!(f, "version {id} integrity mismatch (expect {expect}, got {got})"), + VersionError::Offline => f.write_str("launcher is offline"), } } } @@ -47,7 +48,8 @@ impl Error for VersionError { struct RemoteVersionList { versions: HashMap, - latest: LatestVersions + latest: LatestVersions, + online: bool } #[derive(Serialize, Deserialize, Debug)] @@ -63,7 +65,7 @@ const MANIFEST_CACHE_PATH: &str = ".manifest.json"; impl RemoteVersionList { // errors from this function are fatal so if it's not a super duper bad error then log and ignore it - async fn load_cached_manifest(home: impl AsRef) -> Result, VersionError> { + async fn load_cached_manifest(home: impl AsRef, online: bool) -> Result, VersionError> { let home = home.as_ref(); let cache_info = match fs::read_to_string(home.join(MANIFEST_CACHE_INFO_PATH)).await { Ok(s) => s, @@ -81,7 +83,7 @@ impl RemoteVersionList { }; let now = Utc::now(); - if now.signed_duration_since(cache_info.last_download) > MANIFEST_CACHE_MAX_AGE { + if online && now.signed_duration_since(cache_info.last_download) > MANIFEST_CACHE_MAX_AGE { debug!("Cached version manifest is older than maximum age. Redownloading."); return Ok(None); } @@ -113,15 +115,22 @@ impl RemoteVersionList { } }; + debug!("Using cached version manifest."); + Ok(Some(manifest)) } - async fn load_manifest(home: impl AsRef) -> Result { + async fn load_manifest(home: impl AsRef, online: bool) -> Result { let home = home.as_ref(); - if let Some(manifest) = Self::load_cached_manifest(home).await? { + if let Some(manifest) = Self::load_cached_manifest(home, online).await? { return Ok(manifest); } + if !online { + warn!("Can't download version manifest while offline. Please rerun the launcher in online mode."); + return Err(VersionError::Offline); + } + debug!("Will download version manifest, since we couldn't load the cached version."); let manifest_str = util::create_client().get(URL_VERSION_MANIFEST) @@ -164,8 +173,8 @@ impl RemoteVersionList { Ok(manifest) } - async fn new(home: impl AsRef) -> Result { - let manifest: VersionManifest = Self::load_manifest(&home).await?; + async fn new(home: impl AsRef, online: bool) -> Result { + let manifest: VersionManifest = Self::load_manifest(&home, online).await?; let mut versions = HashMap::new(); for v in manifest.versions { @@ -175,11 +184,14 @@ impl RemoteVersionList { debug!("Done loading remote versions!"); Ok(RemoteVersionList { versions, - latest: manifest.latest + latest: manifest.latest, + online }) } async fn download_version(&self, ver: &VersionManifestVersion, path: &Path) -> Result { + assert!(self.online, "download_version called in offline mode"); + // ensure parent directory exists info!("Downloading version {}.", ver.id); tokio::fs::create_dir_all(path.parent().expect("version .json has no parent (impossible)")).await @@ -329,7 +341,8 @@ impl LocalVersionList { } pub struct VersionList { - remote: Option, + online: bool, + remote: RemoteVersionList, local: LocalVersionList, home: PathBuf } @@ -390,58 +403,44 @@ impl VersionList { } } - pub async fn online(home: &Path) -> Result { + pub async fn new(home: impl AsRef, online: bool) -> Result { + let home = home.as_ref(); Self::create_dir_for(home).await.map_err(|e| VersionError::IO { what: format!("create version directory {}", home.display()), error: e })?; - let remote = RemoteVersionList::new(home).await?; + let remote = RemoteVersionList::new(home, online).await?; let local = LocalVersionList::load_versions(home, |s| remote.versions.contains_key(s)).await?; Ok(VersionList { - remote: Some(remote), - local, - home: home.to_path_buf() - }) - } - - pub async fn offline(home: &Path) -> Result { - Self::create_dir_for(home).await.map_err(|e| VersionError::IO { what: format!("create version directory {}", home.display()), error: e })?; - - let local = LocalVersionList::load_versions(home, |_| false).await?; - - Ok(VersionList { - remote: None, + online, + remote, local, home: home.to_path_buf() }) } pub fn is_online(&self) -> bool { - self.remote.is_some() + self.online } pub fn get_version_lazy(&self, id: &str) -> VersionResult { - self.remote.as_ref().and_then(|r| r.versions.get(id).map(VersionResult::from)) + self.remote.versions.get(id).map(VersionResult::from) .or_else(|| self.local.versions.get(id).map(VersionResult::from)) .unwrap_or(VersionResult::None) } - pub fn get_profile_version_id<'v>(&self, ver: &'v ProfileVersion) -> Option> { + pub fn get_profile_version_id<'v>(&self, ver: &'v ProfileVersion) -> Cow<'v, str> { match ver { - ProfileVersion::LatestRelease => self.remote.as_ref().map(|r| Cow::Owned(r.latest.release.clone())), - ProfileVersion::LatestSnapshot => self.remote.as_ref().map(|r| Cow::Owned(r.latest.snapshot.clone())), - ProfileVersion::Specific(ver) => Some(Cow::Borrowed(ver)) + ProfileVersion::LatestRelease => self.remote.latest.release.clone().into(), + ProfileVersion::LatestSnapshot => self.remote.latest.snapshot.clone().into(), + ProfileVersion::Specific(ver) => Cow::Borrowed(ver) } } pub fn get_remote_version(&self, id: &str) -> Option<&VersionManifestVersion> { - let remote = self.remote.as_ref().expect("get_remote_version called in offline mode!"); - - remote.versions.get(id) + self.remote.versions.get(id) } pub async fn load_remote_version(&self, ver: &VersionManifestVersion) -> Result { - let remote = self.remote.as_ref().expect("load_remote_version called in offline mode!"); - let id = ver.id.as_str(); let mut ver_path = self.home.join(id); ver_path.push(format!("{id}.json")); @@ -451,11 +450,16 @@ impl VersionList { match LocalVersionList::load_version(ver_path.as_path(), Some(ver.sha1)).await { Ok(v) => return Ok(v), Err(e) => { - info!("Redownloading {id}, since the local copy could not be loaded: {e}"); + if self.online { + info!("Redownloading {id}, since the local copy could not be loaded: {e}"); + } else { + warn!("Cannot download {id} (unable to load local copy: {e}). The launcher is offline."); + return Err(VersionError::Offline); + } } } - remote.download_version(ver, ver_path.as_path()).await + self.remote.download_version(ver, ver_path.as_path()).await } pub async fn resolve_version<'v>(&self, ver: &'v CompleteVersion) -> Result, VersionResolveError> { -- cgit v1.2.3-70-g09d2